/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/KeeperProxy.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; 5 | | import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; 6 | | import "./libraries/StructData.sol"; 7 | | 8 | | interface IPerpetualVault { 9 | | function market() external view returns (address); 10 | | function gmxUtils() external view returns (address); 11 | | function run(bool, bool, uint256, MarketPrices memory, bytes[] memory) external; 12 | | function runNextAction(MarketPrices memory, bytes[] memory) external; 13 | | function cancelDeposit() external; 14 | | function cancelOrder() external; 15 | | function claimCollateralRebates(uint256[] memory) external; 16 | | } 17 | | 18 | | interface IGmxUtils { 19 | | function getMarket(address market) external view returns (MarketProps memory); 20 | | } 21 | | 22 | | interface AggregatorV2V3Interface { 23 | | function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80); 24 | | } 25 | | 26 | | interface IERC20 { 27 | | function decimals() external view returns (uint8); 28 | | } 29 | | 30 | | /** 31 | | * @title KeeperProxy 32 | | * @dev This contract acts as a proxy for executing keeper functions on a PerpetualVault. 33 | | * It handles price validation and ensures the correct execution of actions. 34 | | */ 35 | | contract KeeperProxy is Initializable, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable { 36 | | 37 | | uint256 constant BPS = 10_000; 38 | | uint256 private constant GRACE_PERIOD_TIME = 3600; 39 | | AggregatorV2V3Interface internal sequencerUptimeFeed; 40 | | mapping (address => address) public dataFeed; 41 | | uint256 public threshold; 42 | | uint256 maxTimeWindow; 43 | | 44 | | /** 45 | | * @notice Initializes the contract. 46 | | * @dev Sets the initial threshold value and initializes inherited contracts. 47 | | */ 48 | | function initialize() external initializer { 49 | | __Ownable2Step_init(); 50 | | sequencerUptimeFeed = AggregatorV2V3Interface(0xFdB631F5EE196F0ed6FAa767959853A9F217697D); 51 | | threshold = 100; 52 | | maxTimeWindow = 30; 53 | | } 54 | | 55 | | /** 56 | | * @notice Executes a run action on the specified PerpetualVault. 57 | | * @dev Validates the price before executing the run action. 58 | | * @param perpVault The address of the PerpetualVault. 59 | | * @param isOpen Indicates if the position should be opened. 60 | | * @param isLong Indicates if the position is long. 61 | | * @param _leverage The leverage value for the position. 62 | | * @param prices The market prices used for validation. 63 | | * @param _swapData The swap data for the run action. 64 | | */ 65 | | function run( 66 | | address perpVault, 67 | | bool isOpen, 68 | | bool isLong, 69 | | uint256 _leverage, 70 | | MarketPrices memory prices, 71 | | bytes[] memory _swapData 72 | | ) external onlyOwner { 73 | | _validatePrice(perpVault, prices); 74 | | IPerpetualVault(perpVault).run(isOpen, isLong, _leverage, prices, _swapData); 75 | | } 76 | | 77 | | /** 78 | | * @notice Executes the next action on the specified PerpetualVault. 79 | | * @dev Validates the price before executing the next action. 80 | | * @param perpVault The address of the PerpetualVault. 81 | | * @param prices The market prices used for validation. 82 | | * @param _swapData The swap data for the next action. 83 | | */ 84 | | function runNextAction(address perpVault, MarketPrices memory prices, bytes[] memory _swapData) external onlyOwner { 85 | | _validatePrice(perpVault, prices); 86 | | IPerpetualVault(perpVault).runNextAction(prices, _swapData); 87 | | } 88 | | 89 | | /** 90 | | * @notice Call `cancelDeposit` function of a vault 91 | | * @param perpVault The address of the PerpetualVault 92 | | */ 93 | | function cancelDeposit(address perpVault) external onlyOwner { 94 | | IPerpetualVault(perpVault).cancelDeposit(); 95 | | } 96 | | 97 | | /** 98 | | * @notice 99 | | * GMX keepers would not always execute orders in a reasonable amount of time. 100 | | * This function is called when the requested Order is not executed in GMX side. 101 | | */ 102 | | function cancelOrder(address perpVault) external onlyOwner { 103 | | IPerpetualVault(perpVault).cancelOrder(); 104 | | } 105 | | 106 | | function claimCollateralRebates(address perpVault, uint256[] memory timeKeys) external onlyOwner { 107 | | IPerpetualVault(perpVault).claimCollateralRebates(timeKeys); 108 | | } 109 | | 110 | | /** 111 | | * @notice Sets the data feed address for a specific token. 112 | | * @dev Can only be called by the owner of the contract. 113 | | * @param token The address of the token. 114 | | * @param feed The address of the data feed. 115 | | */ 116 | | function setDataFeed(address token, address feed) external onlyOwner { 117 | | require(token != address(0), "zero address"); 118 | | require(feed != address(0), "zero address"); 119 | | dataFeed[token] = feed; 120 | | } 121 | | 122 | | /** 123 | | * @notice Sets the threshold value for price validation. 124 | | * @dev Can only be called by the owner of the contract. 125 | | * @param _threshold The new threshold value. 126 | | */ 127 | | function setThreshold(uint256 _threshold) external onlyOwner { 128 | | require(_threshold > 0, "zero value"); 129 | | threshold = _threshold; 130 | | } 131 | | 132 | | function setMaxTimeWindow(uint256 _maxTimeWindow) external onlyOwner { 133 | | require(_maxTimeWindow > 0, "zero value"); 134 | | maxTimeWindow = _maxTimeWindow; 135 | | } 136 | | 137 | | /** 138 | | * @notice Validates the market prices against the Chainlink data feed. 139 | | * @dev Internal function to check the prices of the market tokens. 140 | | * @param perpVault The address of the PerpetualVault. 141 | | * @param prices The market prices used for validation. 142 | | */ 143 | | function _validatePrice(address perpVault, MarketPrices memory prices) internal view { 144 | | // L2 Sequencer check 145 | | ( 146 | | /*uint80 roundID*/, 147 | | int256 answer, 148 | | uint256 startedAt, 149 | | /*uint256 updatedAt*/, 150 | | /*uint80 answeredInRound*/ 151 | | ) = AggregatorV2V3Interface(sequencerUptimeFeed).latestRoundData(); 152 | | bool isSequencerUp = answer == 0; 153 | | require(isSequencerUp, "sequencer is down"); 154 | | // Make sure the grace period has passed after the sequencer is back up. 155 | | uint256 timeSinceUp = block.timestamp - startedAt; 156 | | require(timeSinceUp > GRACE_PERIOD_TIME, "Grace period is not over"); 157 | | 158 | | address market = IPerpetualVault(perpVault).market(); 159 | | address gmxUtils = IPerpetualVault(perpVault).gmxUtils(); 160 | | MarketProps memory marketData = IGmxUtils(gmxUtils).getMarket(market); 161 | | 162 | | _check(marketData.indexToken, prices.indexTokenPrice.min); 163 | | _check(marketData.indexToken, prices.indexTokenPrice.max); 164 | | _check(marketData.longToken, prices.indexTokenPrice.min); 165 | | _check(marketData.longToken, prices.indexTokenPrice.max); 166 | | _check(marketData.shortToken, prices.shortTokenPrice.min); 167 | | _check(marketData.shortToken, prices.shortTokenPrice.max); 168 | | } 169 | | 170 | | /** 171 | | * @notice Checks the price difference between the given price and the Chainlink price. 172 | | * @dev Internal function to ensure the price difference is within the threshold. 173 | | * @param token The address of the token. 174 | | * @param price The price to be checked. 175 | | */ 176 | | function _check(address token, uint256 price) internal view { 177 | | // https://github.com/code-423n4/2021-06-tracer-findings/issues/145 178 | | (, int chainLinkPrice, , uint256 updatedAt, ) = AggregatorV2V3Interface(dataFeed[token]).latestRoundData(); 179 | | require(updatedAt > block.timestamp - maxTimeWindow, "stale price feed"); 180 | | uint256 decimals = 30 - IERC20(token).decimals(); 181 | | price = price / 10 ** (decimals - 8); // Chainlink price decimals is always 8. 182 | | require(_absDiff(price, uint256(chainLinkPrice)) * BPS / uint256(chainLinkPrice) < threshold, "price offset too big"); 183 | | } 184 | | 185 | | /** 186 | | * @notice Calculates the absolute difference between two numbers. 187 | | * @dev Internal pure function to calculate the absolute difference. 188 | | * @param a The first number. 189 | | * @param b The second number. 190 | | * @return diff The absolute difference between the two numbers. 191 | | */ 192 | | function _absDiff(uint256 a, uint256 b) internal pure returns (uint256 diff) { 193 | | if (a > b) return a - b; 194 | | else return b - a; 195 | | } 196 | | } 197 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/MockParaswapUtils.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 6 | | import {console} from "forge-std/Test.sol"; 7 | | interface IAugustusSwapper { 8 | | function getTokenTransferProxy() external view returns (address); 9 | | } 10 | | 11 | | contract MockParaSwapUtils { 12 | | using SafeERC20 for IERC20; 13 | | 14 | | address PARASWAP_ROUTER; 15 | | bool routerSet; 16 | | 17 | | function setRouter(address _paraswapRouter) public { 18 | | require(!routerSet); 19 | | PARASWAP_ROUTER = _paraswapRouter; 20 | | routerSet = true; 21 | | } 22 | | 23 | * | function swap(address to, bytes memory callData) public { 24 | * | _validateCallData(to, callData); 25 | * | address approvalAddress = IAugustusSwapper(to).getTokenTransferProxy(); 26 | * | address fromToken; 27 | * | uint256 fromAmount; 28 | | assembly { 29 | * | fromToken := mload(add(callData, 36)) //@audit replaced 68th byte by fuzzer 30 | * | fromAmount := mload(add(callData, 100)) 31 | | } 32 | * | IERC20(fromToken).safeApprove(approvalAddress, fromAmount); 33 | * | (bool success, ) = to.call(callData); 34 | * | require(success, "paraswap call reverted"); 35 | | } 36 | | 37 | * | function _validateCallData( 38 | | address to, 39 | | bytes memory callData 40 | * | ) internal view { 41 | * | assert(PARASWAP_ROUTER != address(0)); 42 | * | require(to == PARASWAP_ROUTER, "invalid paraswap callee"); 43 | | 44 | * | address receiver; 45 | | assembly { 46 | * | receiver := mload(add(callData, 196)) 47 | | } 48 | * | require(receiver == address(this), "invalid paraswap calldata"); 49 | | } 50 | | } 51 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/PerpetualVault.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | pragma abicoder v2; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; 8 | | import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; 9 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 10 | | import "./libraries/Order.sol"; 11 | | import "./libraries/ParaSwapUtils.sol"; 12 | | import "./interfaces/gmx/IDataStore.sol"; 13 | | import "./interfaces/gmx/IReader.sol"; 14 | | import "./interfaces/gmx/IExchangeRouter.sol"; 15 | | import "./interfaces/IGmxUtils.sol"; 16 | | import {Test, console} from "forge-std/Test.sol"; 17 | | 18 | | /** 19 | | * @notice 20 | | * a vault contract that trades on GMX market and Paraswap DEX Aggregator 21 | | * it gets the signal(long/short/close flag and leverage value) from the off-chain script. 22 | | * if signal is long and leverage is 1x, swap collateral to `indexToken`。 23 | | * if signal is long with leverage above 1x, open a long position with a specified leverage on gmx market. 24 | | * if signal is short, open a short position with a specified leverage on gmx market. 25 | | * 26 | | * For now, we only support the GMX market in which `indexToken` is the same as `longToken`. 27 | | * We think the price impact of deposit and withdraw as a swap slippage loss. As if the more swap amount in dex, the much loss we get. 28 | | * GMX charges negative fee against collateral so collateral amount is decreased over time. It makes leverage value increasing. 29 | | * We have offchain script to address this. The offchain script monitors leverage value and adjusts when it exceeds the risky value to avoid liquidation. 30 | | */ 31 | | contract PerpetualVault is 32 | | Initializable, 33 | | Ownable2StepUpgradeable, 34 | | ReentrancyGuardUpgradeable 35 | | { 36 | | using SafeERC20 for IERC20; 37 | | 38 | | struct SwapProgress { 39 | | // swap process involves asynchronous operation so store swap progress data 40 | | bool isCollateralToIndex; // if swap `collateralToken` to `indexToken`, true and vice versa. 41 | | uint256 swapped; // the amount of output token that has already been swapped. 42 | | uint256 remaining; // the amount of input token that remains to be swapped 43 | | } 44 | | 45 | | enum NextActionSelector { 46 | | NO_ACTION, // state where no action is required 47 | | INCREASE_ACTION, // represents increasing actions such as increasing a GMX perps position or increasing a spot position 48 | | SWAP_ACTION, // represents swapping a token, either collateral to index or vice versa 49 | | WITHDRAW_ACTION, // represents withdrawing funds 50 | | COMPOUND_ACTION, // whenver claiming positive funding fee, we could have idle funds in the vault. 51 | | // If it's enough to deposit more into GMX, triggers `COMPOUND_ACTION`. 52 | | SETTLE_ACTION, // settle fees and ensure state is up-to-date prior to withdrawals 53 | | FINALIZE 54 | | } 55 | | 56 | | enum FLOW { 57 | | NONE, 58 | | DEPOSIT, 59 | | SIGNAL_CHANGE, 60 | | WITHDRAW, 61 | | COMPOUND 62 | | } 63 | | 64 | | struct Action { 65 | | NextActionSelector selector; 66 | | bytes data; 67 | | } 68 | | 69 | | struct DepositInfo { 70 | | uint256 amount; // amount of deposit 71 | | uint256 shares; // amount of share corresponding to deposit amount 72 | | address owner; // depositor address 73 | | uint256 executionFee; // execution fee 74 | | uint256 timestamp; // timestamp of deposit 75 | | address recipient; // address of recipient when withdrawing, which is set at the moment of withdrawal request 76 | | } 77 | | 78 | | string public name; 79 | | 80 | | // Vault variables 81 | | uint256 public constant PRECISION = 1e30; 82 | * | uint256 public constant BASIS_POINTS_DIVISOR = 10_000; 83 | | 84 | * | uint256 public totalShares; 85 | * | uint256 public counter; 86 | * | mapping(uint256 => DepositInfo) public depositInfo; 87 | | mapping(address => EnumerableSet.UintSet) userDeposits; 88 | | 89 | | address public market; 90 | * | address public indexToken; 91 | * | IERC20 public collateralToken; 92 | | IGmxUtils public gmxUtils; 93 | | 94 | | address public keeper; 95 | * | address public treasury; 96 | * | bytes32 public curPositionKey; // current open positionKey 97 | * | uint256 public maxDepositAmount; // max cap of collateral token that can be managrable in vault 98 | * | uint256 public minDepositAmount; // min deposit amount of collateral 99 | * | uint256 public totalDepositAmount; // current total collateral token amount in the vault 100 | | uint256 public minEth; // minimum eth amount to run signal change action 101 | | uint256 public governanceFee; // percentage of fee to charge 102 | | uint256 public callbackGasLimit; // gas amount to compensate keeper calls and GMX callback function 103 | * | uint256 public lockTime; // `lockTime` prevents the immediate withdrawal attempts after deposit 104 | | uint256 public leverage; // GMX position leverage value (decimals is 10000) 105 | | 106 | * | Action public nextAction; 107 | * | FLOW public flow; 108 | | bytes flowData; 109 | * | bool public beenLong; // true if current open position is long 110 | * | bool public positionIsClosed; // true if there's no open position 111 | | bool _gmxLock; // this is true while gmx action is in progress. i.e. from gmx call to gmx callback 112 | | 113 | * | SwapProgress public swapProgressData; // in order to deal with gmx swap failures, we utilize this struct to keep track of what has already been swapped to avoid overswapping 114 | | MarketPrices marketPrices; 115 | | bool public depositPaused; // if true, deposit is paused 116 | | 117 | | event Minted( 118 | | uint256 depositId, 119 | | address depositor, 120 | | uint256 shareAmount, 121 | | uint256 depositAmount 122 | | ); 123 | | event Burned( 124 | | uint256 depositId, 125 | | address recipient, 126 | | uint256 shareAmount, 127 | | uint256 amount 128 | | ); 129 | | event DexSwap( 130 | | address inputToken, 131 | | uint256 inputAmount, 132 | | address outputToken, 133 | | uint256 outputAmount 134 | | ); 135 | | event GmxSwap( 136 | | address inputToken, 137 | | uint256 inputAmount, 138 | | address outputToken, 139 | | uint256 outputAmount 140 | | ); 141 | | event Settled(uint256 positiveFundingFeeAmount, uint256 negativeFeeAmount); 142 | | event FeeCollected(address token, uint256 amount); 143 | | event GmxPositionCallbackCalled(bytes32 requestKey, bool success); 144 | | event SignalChanged(bool isOpen, bool isLong, uint256 leverage); 145 | | event TokenTranferFailed(address recipient, uint256 amount); 146 | | 147 | | modifier onlyKeeper() { 148 | * | require(msg.sender == keeper, "!keeper"); 149 | | _; 150 | | } 151 | | 152 | | // Lock the contract from the moment we create position to the moment we get the callback from GMX keeper 153 | | modifier gmxLock() { 154 | * | require(_gmxLock == false, "gmx action lock"); 155 | | _; 156 | | } 157 | | 158 | | // we prevent user interactions while a flow is still being in progress. 159 | | modifier noneFlow() { 160 | * | require(flow == FLOW.NONE, "flow in progress"); 161 | | _; 162 | | } 163 | | 164 | | /** 165 | | * @notice 166 | | * `collateralToken` can be ETH, WETH, BTC, LINK, UNI, USDC, USDT, DAI, FRAX. 167 | | * @param _name Perpetual Vault indentifier 168 | | * @param _market address of GMX market 169 | | * @param _keeper keeper address 170 | | * @param _treasury fee receiver 171 | | * @param _gmxUtils address of GMXUtils contract 172 | | * @param _minDepositAmount minimum deposit amount 173 | | * @param _maxDepositAmount maximum deposit amount 174 | | */ 175 | | function initialize( 176 | | string memory _name, 177 | | address _market, 178 | | address _keeper, 179 | | address _treasury, 180 | | address _gmxUtils, 181 | | uint256 _minDepositAmount, 182 | | uint256 _maxDepositAmount 183 | | ) external initializer { 184 | | __Ownable2Step_init(); 185 | | __ReentrancyGuard_init(); 186 | | name = _name; 187 | | require(_market != address(0), "zero address"); 188 | | require(_gmxUtils != address(0), "zero address"); 189 | | market = _market; 190 | | IGmxUtils(_gmxUtils).setPerpVault(address(this)); 191 | | gmxUtils = IGmxUtils(_gmxUtils); 192 | | MarketProps memory marketInfo = IGmxUtils(_gmxUtils).getMarket(market); 193 | | indexToken = marketInfo.indexToken; 194 | | collateralToken = IERC20(marketInfo.shortToken); 195 | | require(_keeper != address(0), "zero address"); 196 | | require(_treasury != address(0), "zero address"); 197 | | keeper = _keeper; 198 | | treasury = _treasury; 199 | | governanceFee = 500; // 5% 200 | | minDepositAmount = _minDepositAmount; 201 | | maxDepositAmount = _maxDepositAmount; 202 | | minEth = 0.002 ether; 203 | | callbackGasLimit = 2_000_000; 204 | | positionIsClosed = true; 205 | | lockTime = 7 * 24 * 3600; // 1 week 206 | | } 207 | | 208 | | /** 209 | | * @notice Deposits collateral tokens into the vault. 210 | | * @dev This function checks if deposits are paused, validates the deposit amount, 211 | | * and transfers the collateral tokens from the sender to the contract. 212 | | * If the position is closed, it directly mints shares for the deposit amount. 213 | | * If the position is open, it sets up the next action to register the requested position params. 214 | | * @param amount The amount of collateral tokens to deposit. 215 | | */ 216 | | function deposit( 217 | | uint256 amount 218 | | ) external payable virtual nonReentrant noneFlow { 219 | | //NOTE: changed by fuzzer 220 | | require(depositPaused == false, "paused"); 221 | | flow = FLOW.DEPOSIT; 222 | | // flowData = abi.encode(msg.sender); 223 | | require(amount >= minDepositAmount, "insufficient amount"); 224 | | require( 225 | | totalDepositAmount + amount <= maxDepositAmount, 226 | | "exceeds max deposit cap" 227 | | ); 228 | | collateralToken.safeTransferFrom(msg.sender, address(this), amount); 229 | | counter++; 230 | | depositInfo[counter] = DepositInfo( 231 | | amount, 232 | | 0, 233 | | msg.sender, 234 | | 0, 235 | | block.timestamp, 236 | | address(0) 237 | | ); 238 | | totalDepositAmount += amount; 239 | | EnumerableSet.add(userDeposits[msg.sender], counter); 240 | | 241 | | if (positionIsClosed) { 242 | | _mint(counter, amount, false); 243 | | _finalize(hex""); 244 | | } else { 245 | | _payExecutionFee(counter); 246 | | // mint share token in the NextAction to involve off-chain price data and improve security 247 | | nextAction.selector = NextActionSelector.INCREASE_ACTION; 248 | | nextAction.data = abi.encode(beenLong, leverage); 249 | | } 250 | | } 251 | | 252 | | /** 253 | | * @notice Withdraws collateral of user. 254 | | * @dev If position is GMX position, first call `settle` function to settle pending fees 255 | | * in order to avoid charging all fees from the withdrawer. 256 | | * @param recipient The address to receive the tokens. 257 | | * @param depositId The deposit ID to withdraw. 258 | | */ 259 | | function withdraw( 260 | | address recipient, 261 | | uint256 depositId 262 | | ) public payable virtual nonReentrant noneFlow { 263 | | //NOTE: changed by fuzzer 264 | | flow = FLOW.WITHDRAW; 265 | | flowData = abi.encode(depositId, msg.sender); 266 | | 267 | | require(recipient != address(0), "zero address"); 268 | | require( 269 | | depositInfo[depositId].timestamp + lockTime < block.timestamp, 270 | | "locked" 271 | | ); 272 | | require( 273 | | EnumerableSet.contains(userDeposits[msg.sender], depositId), 274 | | "not a valid user" 275 | | ); 276 | | require(depositInfo[depositId].shares > 0, "zero share value"); 277 | | 278 | | depositInfo[depositId].recipient = recipient; 279 | | if (curPositionKey != bytes32(0)) { 280 | | _payExecutionFee(depositId); 281 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 282 | | _settle(); // Settles any outstanding fees and updates state before processing withdrawal 283 | | } else { 284 | | _withdraw(depositId, hex"00"); 285 | | } 286 | | } 287 | | 288 | | /** 289 | | * @notice Off-chain script calls `run` function to change position type (long/short/close). 290 | | * @param isOpen If true, open a position; if false, close the current position. 291 | | * @param isLong If true, open a long position; if false, open a short position. 292 | | * @param _leverage Leverage value in GMX protocol. 293 | | * @param prices GMX price data of market tokens from GMX API call. 294 | | * @param metadata Swap transaction data generated by off-chain script. 295 | | */ 296 | | function run( 297 | | bool isOpen, 298 | | bool isLong, 299 | | uint256 _leverage, 300 | | MarketPrices memory prices, 301 | | bytes[] memory metadata 302 | | ) external virtual nonReentrant noneFlow onlyKeeper { 303 | | 304 | | //NOTE: visibility changed by fuzzer 305 | | require( 306 | | address(gmxUtils).balance > minEth, 307 | | "lower than minimum eth balance" 308 | | ); 309 | | flow = FLOW.SIGNAL_CHANGE; 310 | | flowData = abi.encode(_leverage, msg.sender); 311 | | marketPrices = prices; 312 | | 313 | | if (isOpen) { 314 | | if (positionIsClosed) { 315 | | require(_isFundIdle(), "insufficient balance to open position"); 316 | | if (_isLongOneLeverage(isLong, _leverage)) { 317 | | _runSwap(metadata, true); 318 | | } else { 319 | | uint256 acceptablePrice = abi.decode( 320 | | metadata[0], 321 | | (uint256) 322 | | ); 323 | | _createIncreasePosition(isLong, _leverage, acceptablePrice); 324 | | } 325 | | } else { 326 | | if (beenLong == isLong) { 327 | | revert("no action needed"); 328 | | } else { 329 | | // Close current position first and then open the requested position in the next action 330 | | nextAction.selector = NextActionSelector.INCREASE_ACTION; 331 | | nextAction.data = abi.encode(isLong, _leverage); 332 | | if (_isLongOneLeverage(beenLong, leverage)) { 333 | | _runSwap(metadata, false); 334 | | } else { 335 | | uint256 acceptablePrice = abi.decode( 336 | | metadata[0], 337 | | (uint256) 338 | | ); 339 | | _createDecreasePosition( 340 | | 0, 341 | | 0, 342 | | beenLong, 343 | | acceptablePrice 344 | | ); 345 | | } 346 | | } 347 | | } 348 | | } else { 349 | | if (positionIsClosed == false) { 350 | | if (_isLongOneLeverage(beenLong, leverage)) { 351 | | _runSwap(metadata, false); 352 | | } else { 353 | | uint256 acceptablePrice = abi.decode( 354 | | metadata[0], 355 | | (uint256) 356 | | ); 357 | | _createDecreasePosition(0, 0, beenLong, acceptablePrice); 358 | | } 359 | | } else { 360 | | revert("no action needed"); 361 | | } 362 | | } 363 | | } 364 | | 365 | | /** 366 | | * @notice `flow` is not completed in one tx. So in that case, set up the next action data 367 | | * and run the `nextAction`. 368 | | * @param prices GMX price data of market tokens from GMX API call 369 | | * @param metadata swap tx data. generated by off-chain script 370 | | */ 371 | | function runNextAction( 372 | | MarketPrices memory prices, 373 | | bytes[] memory metadata 374 | | ) external virtual nonReentrant gmxLock onlyKeeper { 375 | | //NOTE: changed by fuzzer 376 | | marketPrices = prices; 377 | | Action memory _nextAction = nextAction; 378 | | delete nextAction; 379 | | if (_nextAction.selector == NextActionSelector.INCREASE_ACTION) { 380 | | (bool _isLong, uint256 _leverage) = abi.decode( 381 | | _nextAction.data, 382 | | (bool, uint256) 383 | | ); 384 | | 385 | | if (_isLongOneLeverage(_isLong, _leverage)) { 386 | | _runSwap(metadata, true); 387 | | } else { 388 | | // swap indexToken that could be generated from the last action into collateralToken 389 | | // use only DexSwap 390 | | if (metadata[1].length > 0) { 391 | | (PROTOCOL _protocol, bytes memory data) = abi.decode( 392 | | metadata[0], 393 | | (PROTOCOL, bytes) 394 | | ); 395 | | require(_protocol == PROTOCOL.DEX, "invalid metadata"); 396 | | _doDexSwap(data, false); 397 | | } 398 | | uint256 acceptablePrice = abi.decode(metadata[0], (uint256)); 399 | | _createIncreasePosition(_isLong, _leverage, acceptablePrice); 400 | | } 401 | | } else if (_nextAction.selector == NextActionSelector.WITHDRAW_ACTION) { 402 | | // swap indexToken that could be generated from settle action into collateralToken 403 | | // use only DexSwap 404 | | if (metadata[1].length > 0) { 405 | | (PROTOCOL _protocol, bytes memory data) = abi.decode( 406 | | metadata[0], 407 | | (PROTOCOL, bytes) 408 | | ); 409 | | require(_protocol == PROTOCOL.DEX, "invalid metadata"); 410 | | _doDexSwap(data, false); 411 | | } 412 | | (uint256 depositId, ) = abi.decode(flowData, (uint256, address)); 413 | | 414 | | _withdraw(depositId, metadata[0]); 415 | | } else if (_nextAction.selector == NextActionSelector.SWAP_ACTION) { 416 | | (, bool isCollateralToIndex) = abi.decode( 417 | | _nextAction.data, 418 | | (uint256, bool) 419 | | ); 420 | | _runSwap(metadata, isCollateralToIndex); 421 | | } else if (_nextAction.selector == NextActionSelector.SETTLE_ACTION) { 422 | | _settle(); 423 | | } else if (_nextAction.selector == NextActionSelector.FINALIZE) { 424 | | if (metadata.length > 0) { 425 | | _runSwap(metadata, false); 426 | | } 427 | | _finalize(_nextAction.data); 428 | | } else if (positionIsClosed == false && _isFundIdle()) { 429 | | flow = FLOW.COMPOUND; 430 | | if (_isLongOneLeverage(beenLong, leverage)) { 431 | | _runSwap(metadata, true); 432 | | } else { 433 | | uint256 acceptablePrice = abi.decode(metadata[0], (uint256)); 434 | | _createIncreasePosition(beenLong, leverage, acceptablePrice); 435 | | } 436 | | } 437 | | } 438 | | 439 | | /** 440 | | * @notice Cancel the ongoing deposit action. 441 | | */ 442 | * | function cancelDeposit() external nonReentrant gmxLock onlyKeeper { 443 | * | require(flow == FLOW.DEPOSIT, "invalid"); 444 | * | uint256 depositId = counter; 445 | * | collateralToken.safeTransfer( 446 | * | depositInfo[depositId].owner, 447 | * | depositInfo[depositId].amount 448 | | ); 449 | * | totalDepositAmount = totalDepositAmount - depositInfo[depositId].amount; 450 | * | EnumerableSet.remove( 451 | * | userDeposits[depositInfo[depositId].owner], 452 | * | depositId 453 | | ); 454 | | 455 | | // refund fee 456 | * | uint256 usedFee = callbackGasLimit * tx.gasprice; 457 | * | if (depositInfo[counter].executionFee > usedFee) { 458 | | IGmxUtils(gmxUtils).refundExecutionFee( 459 | | depositInfo[counter].owner, 460 | | depositInfo[counter].executionFee - usedFee 461 | | ); 462 | | } 463 | | 464 | * | delete depositInfo[depositId]; 465 | * | delete nextAction; 466 | * | delete flowData; 467 | * | flow = FLOW.NONE; 468 | | } 469 | | 470 | | /** 471 | | * @notice Cancel order when order is not executed from GMX side 472 | | * Cancelling order is valid after the expiration time has passed since the order request is registered. 473 | | */ 474 | | function cancelOrder() external nonReentrant onlyKeeper { 475 | | require(_gmxLock, "invalid call"); 476 | | IGmxUtils(gmxUtils).cancelOrder(); 477 | | } 478 | | 479 | | /** 480 | | * @notice 481 | | * GMX cap negative price impact on decrease orders. 482 | | * If a trade is closed with a price impact higher than this percentage, 483 | | * then the additional impact would become claimable after a few days. 484 | | * This function is used to claim this manually. 485 | | * Resolves who and how much via off-chain script 486 | | */ 487 | | function claimCollateralRebates( 488 | | uint256[] memory timeKeys 489 | | ) external nonReentrant noneFlow onlyKeeper { 490 | | address[] memory markets = new address[](1); 491 | | markets[0] = market; 492 | | address[] memory tokens = new address[](1); 493 | | tokens[0] = address(collateralToken); 494 | | 495 | | IGmxUtils(gmxUtils).claimCollateralRebates( 496 | | markets, 497 | | tokens, 498 | | timeKeys, 499 | | treasury 500 | | ); 501 | | } 502 | | 503 | | /** 504 | | * @notice Callback function that is called when an order on GMX is executed successfully. 505 | | * This function handles the post-execution logic based on the type of order that was executed. 506 | | * @dev This callback function must never be reverted. It should wrap revertible external calls with `try-catch`. 507 | | * @param requestKey The request key of the executed order. 508 | | * @param positionKey The position key. 509 | | * @param orderResultData Data from the order execution. 510 | | */ 511 | | function afterOrderExecution( 512 | | bytes32 requestKey, 513 | | bytes32 positionKey, 514 | | IGmxUtils.OrderResultData memory orderResultData 515 | | ) external virtual nonReentrant { 516 | | require(msg.sender == address(gmxUtils), "invalid caller"); 517 | | _updateMarketPrice(); 518 | | 519 | | _gmxLock = false; 520 | | // If the current action is `settle` 521 | | if (orderResultData.isSettle) { 522 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 523 | | emit GmxPositionCallbackCalled(requestKey, true); 524 | | // emit Settled(positiveFundingFeeAmount, negativeFeeAmount); 525 | | return; 526 | | } 527 | | if (orderResultData.orderType == Order.OrderType.MarketIncrease) { 528 | | curPositionKey = positionKey; 529 | | if (flow == FLOW.DEPOSIT) { 530 | | uint256 curAmount = _totalAmount(marketPrices); 531 | | uint256 prevAmount = abi.decode(flowData, (uint256)); 532 | | if (curAmount > prevAmount) { 533 | | uint256 increased = (curAmount - prevAmount) / 534 | | marketPrices.shortTokenPrice.max; 535 | | _mint(counter, increased, false); 536 | | } 537 | | nextAction.selector = NextActionSelector.FINALIZE; 538 | | } else { 539 | | uint256 _leverage; 540 | | if (flowData.length > 0) { 541 | | (_leverage, ) = abi.decode(flowData, (uint256, address)); 542 | | } else { 543 | | _leverage = leverage; 544 | | } 545 | | _updateState(false, _leverage, orderResultData.isLong); 546 | | } 547 | | } else if ( 548 | | orderResultData.orderType == Order.OrderType.MarketDecrease 549 | | ) { 550 | | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey); 551 | | if (sizeInUsd == 0) { 552 | | curPositionKey = bytes32(0); 553 | | } 554 | | if (flow == FLOW.WITHDRAW) { 555 | | nextAction.selector = NextActionSelector.FINALIZE; 556 | | uint256 prevCollateralBalance = collateralToken.balanceOf( 557 | | address(this) 558 | | ) - orderResultData.outputAmount; 559 | | nextAction.data = abi.encode( 560 | | prevCollateralBalance, 561 | | sizeInUsd == 0, 562 | | false 563 | | ); 564 | | // _handleReturn(orderResultData.outputAmount, sizeInUsd == 0, false); 565 | | } else { 566 | | nextAction.selector = NextActionSelector.FINALIZE; 567 | | _updateState(true, 0, false); 568 | | } 569 | | } else if (orderResultData.orderType == Order.OrderType.MarketSwap) { 570 | | uint256 outputAmount = orderResultData.outputAmount; 571 | | if (swapProgressData.isCollateralToIndex) { 572 | | emit GmxSwap( 573 | | address(collateralToken), 574 | | swapProgressData.remaining, 575 | | indexToken, 576 | | outputAmount 577 | | ); 578 | | } else { 579 | | emit GmxSwap( 580 | | indexToken, 581 | | swapProgressData.remaining, 582 | | address(collateralToken), 583 | | outputAmount 584 | | ); 585 | | } 586 | | 587 | | if (flow == FLOW.DEPOSIT) { 588 | | _mint(counter, outputAmount + swapProgressData.swapped, false); 589 | | _finalize(hex""); 590 | | } else if (flow == FLOW.WITHDRAW) { 591 | | _handleReturn( 592 | | outputAmount + swapProgressData.swapped, 593 | | false, 594 | | false 595 | | ); 596 | | } else { 597 | | // Same as if (flow == FLOW.SIGNAL_CHANGE || FLOW.COMPOUND) 598 | | if (orderResultData.outputToken == indexToken) { 599 | | _updateState(false, BASIS_POINTS_DIVISOR, true); 600 | | } else { 601 | | _updateState(true, 0, false); 602 | | } 603 | | } 604 | | } 605 | | 606 | | emit GmxPositionCallbackCalled(requestKey, true); 607 | | // Consider emitting an event that shows the current leverage value later 608 | | } 609 | | 610 | | /** 611 | | * @notice Callback function triggered when an order execution on GMX is canceled due to an error. 612 | | * @param requestKey The request key of the executed order. 613 | | * @param orderType The type of order. 614 | | * @param orderResultData The result data of the order execution. 615 | | */ 616 | | function afterOrderCancellation( 617 | | bytes32 requestKey, 618 | | Order.OrderType orderType, 619 | | IGmxUtils.OrderResultData memory orderResultData 620 | | ) external virtual { 621 | | require(msg.sender == address(gmxUtils), "invalid caller"); 622 | | _gmxLock = false; 623 | | if (orderResultData.isSettle) { 624 | | // Retry settle action. 625 | | nextAction.selector = NextActionSelector.SETTLE_ACTION; 626 | | } else if (orderType == Order.OrderType.MarketSwap) { 627 | | // If GMX swap fails, retry in the next action. 628 | | nextAction.selector = NextActionSelector.SWAP_ACTION; 629 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken 630 | | nextAction.data = abi.encode( 631 | | swapProgressData.remaining, 632 | | swapProgressData.isCollateralToIndex 633 | | ); 634 | | } else { 635 | | if (flow == FLOW.DEPOSIT) { 636 | | nextAction.selector = NextActionSelector.INCREASE_ACTION; 637 | | nextAction.data = abi.encode(beenLong, leverage); 638 | | } else if (flow == FLOW.WITHDRAW) { 639 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 640 | | } else { 641 | | // If signal change fails, the offchain script starts again from the current status. 642 | | delete flowData; 643 | | flow = FLOW.NONE; 644 | | } 645 | | } 646 | | emit GmxPositionCallbackCalled(requestKey, false); 647 | | } 648 | | 649 | | function afterOrderFrozen( 650 | | bytes32 key, 651 | | Order.OrderType, 652 | | bool, 653 | | bytes32 654 | | ) external {} 655 | | 656 | | ////////////////////////////// 657 | | //// View Functions //// 658 | | ////////////////////////////// 659 | | 660 | | /** 661 | | * @notice 662 | | * return total value of vault in terms of collteral token 663 | | * @param prices gmx price data of market tokens that is from gmx api call 664 | | */ 665 | | function totalAmount( 666 | | MarketPrices memory prices 667 | | ) external view returns (uint256) { 668 | | return _totalAmount(prices); 669 | | } 670 | | 671 | | /** 672 | | * @notice 673 | | * get the current gmx position information. 674 | | */ 675 | * | function getPositionInfo( 676 | | MarketPrices memory prices 677 | | ) 678 | | external 679 | | view 680 | * | returns (address, address, uint256, uint256, uint256, uint256, bool) 681 | | { 682 | * | IGmxUtils.PositionData memory positionData = gmxUtils.getPositionInfo( 683 | * | curPositionKey, 684 | * | prices 685 | | ); 686 | * | return ( 687 | * | market, 688 | * | address(collateralToken), 689 | * | positionData.sizeInUsd, 690 | * | positionData.sizeInTokens, 691 | * | positionData.collateralAmount, 692 | * | positionData.netValue, 693 | * | positionData.isLong 694 | | ); 695 | | } 696 | | 697 | | /** 698 | | * @notice 699 | | * get all deposit ids of a user 700 | | * @param user address of a user 701 | | */ 702 | * | function getUserDeposits( 703 | | address user 704 | * | ) external view returns (uint256[] memory depositIds) { 705 | * | uint256 length = EnumerableSet.length(userDeposits[user]); 706 | * | depositIds = new uint256[](length); 707 | * | for (uint8 i = 0; i < length; ) { 708 | * | depositIds[i] = EnumerableSet.at(userDeposits[user], i); 709 | | unchecked { 710 | * | i = i + 1; 711 | | } 712 | | } 713 | | } 714 | | 715 | | /** 716 | | * @notice 717 | | * get the estimated execution fee amount to run deposit or withdrawal 718 | | */ 719 | * | function getExecutionGasLimit( 720 | | bool isDeposit 721 | * | ) public view returns (uint256 minExecutionGasLimit) { 722 | * | if (positionIsClosed == false) { 723 | * | if (_isLongOneLeverage(beenLong, leverage)) { 724 | * | minExecutionGasLimit = gmxUtils.getExecutionGasLimit( 725 | * | Order.OrderType.MarketSwap, 726 | * | callbackGasLimit 727 | | ); 728 | | } else { 729 | * | if (isDeposit) { 730 | * | minExecutionGasLimit = gmxUtils.getExecutionGasLimit( 731 | * | Order.OrderType.MarketIncrease, 732 | * | callbackGasLimit 733 | | ); 734 | | } else { 735 | | // withdraw action has 2 gmx call parts: settle + decrease position 736 | * | minExecutionGasLimit = 737 | * | gmxUtils.getExecutionGasLimit( 738 | * | Order.OrderType.MarketDecrease, 739 | * | callbackGasLimit 740 | | ) * 741 | * | 2; 742 | | } 743 | | } 744 | | } 745 | | } 746 | | 747 | | /** 748 | | * @notice 749 | | * check if there is the next action 750 | | */ 751 | | function isNextAction() external view returns (NextActionSelector) { 752 | | if (_gmxLock) { 753 | | return NextActionSelector.NO_ACTION; 754 | | } else if (nextAction.selector != NextActionSelector.NO_ACTION) { 755 | | return nextAction.selector; 756 | | } else if (positionIsClosed == false && _isFundIdle()) { 757 | | return NextActionSelector.COMPOUND_ACTION; 758 | | } else { 759 | | return NextActionSelector.NO_ACTION; 760 | | } 761 | | } 762 | | 763 | | /** 764 | | * @notice Checks if the contract is currently busy. 765 | | * @return bool Returns true if the contract is busy, false otherwise. 766 | | */ 767 | * | function isBusy() external view returns (bool) { 768 | * | return flow != FLOW.NONE; 769 | | } 770 | | 771 | | /** 772 | | * @notice Checks if the GMX lock is currently active. 773 | | * @return bool Returns true if the GMX lock is active, false otherwise. 774 | | */ 775 | * | function isLock() external view returns (bool) { 776 | * | return _gmxLock; 777 | | } 778 | | 779 | | /** 780 | | * @notice Sets the keeper address. 781 | | * @param _keeper The address of the new keeper. 782 | | */ 783 | | function setKeeper(address _keeper) external onlyOwner { 784 | | require(_keeper != address(0), "zero address"); 785 | | keeper = _keeper; 786 | | } 787 | | 788 | | /** 789 | | * @notice Sets the treasury address. 790 | | * @param _treasury The address of the new treasury. 791 | | */ 792 | | function setTreasury(address _treasury) external onlyOwner { 793 | | require(_treasury != address(0), "zero address"); 794 | | treasury = _treasury; 795 | | } 796 | | 797 | | function setMinDepositAmount(uint256 _minDepositAmount) external onlyOwner { 798 | | minDepositAmount = _minDepositAmount; 799 | | } 800 | | 801 | | /** 802 | | * @notice Sets the maximum deposit amount. 803 | | * @param _maxDepositAmount The new maximum deposit amount. 804 | | */ 805 | | function setMaxDepositAmount(uint256 _maxDepositAmount) external onlyOwner { 806 | | maxDepositAmount = _maxDepositAmount; 807 | | } 808 | | 809 | | /** 810 | | * @notice Sets the minimum ETH balance. 811 | | * @param _minEth The new minimum ETH balance. 812 | | */ 813 | | function setMinEth(uint256 _minEth) external onlyOwner { 814 | | require(_minEth > 0, "minimum"); 815 | | minEth = _minEth; 816 | | } 817 | | 818 | | /** 819 | | * @notice Sets the callback gas limit. 820 | | * @param _callbackGasLimit The new callback gas limit. 821 | | */ 822 | | function setCallbackGasLimit(uint256 _callbackGasLimit) external onlyOwner { 823 | | require(_callbackGasLimit > 0, "zero value"); 824 | | callbackGasLimit = _callbackGasLimit; 825 | | } 826 | | 827 | | /** 828 | | * @notice Sets the lock time. 829 | | * @param _lockTime The new lock time. 830 | | */ 831 | | function setLockTime(uint256 _lockTime) external onlyOwner { 832 | | require(_lockTime > 0, "zero value"); 833 | | lockTime = _lockTime; 834 | | } 835 | | 836 | | /** 837 | | * @notice Sets the deposit paused state. 838 | | * @param _depositPaused If true, deposits are paused; if false, deposits are active. 839 | | */ 840 | | function setDepositPaused(bool _depositPaused) external onlyOwner { 841 | | depositPaused = _depositPaused; 842 | | } 843 | | 844 | | ////////////////////////////// 845 | | //// Internal Functions //// 846 | | ////////////////////////////// 847 | | 848 | | /** 849 | | * @notice this function is an end of deposit flow. 850 | | * @dev should update all necessary global state variables 851 | | * 852 | | * @param depositId `depositId` of mint operation 853 | | * @param amount actual deposit amount. if `_isLongOneLeverage` is `true`, amount of `indexToken`, or amount of `collateralToken` 854 | | */ 855 | * | function _mint(uint256 depositId, uint256 amount, bool refundFee) internal { 856 | * | uint256 _shares; 857 | * | if (totalShares == 0) { 858 | * | _shares = depositInfo[depositId].amount * 1e8; 859 | * | } else { 860 | * | uint256 totalAmountBefore; 861 | | 862 | * | if ( 863 | * | positionIsClosed == false && 864 | * | _isLongOneLeverage(beenLong, leverage) 865 | | ) { 866 | * | totalAmountBefore = 867 | * | IERC20(indexToken).balanceOf(address(this)) - 868 | * | amount; 869 | | } else { 870 | * | totalAmountBefore = _totalAmount(marketPrices) - amount; 871 | | } 872 | * | _shares = (amount * totalShares) / totalAmountBefore; 873 | | } 874 | * | depositInfo[depositId].shares = _shares; 875 | * | totalShares = totalShares + _shares; 876 | | 877 | * | if (refundFee) { 878 | | uint256 usedFee = callbackGasLimit * tx.gasprice; 879 | | if (depositInfo[counter].executionFee > usedFee) { 880 | | IGmxUtils(gmxUtils).refundExecutionFee( 881 | | depositInfo[counter].owner, 882 | | depositInfo[counter].executionFee - usedFee 883 | | ); 884 | | } 885 | | } 886 | | 887 | * | emit Minted(depositId, depositInfo[depositId].owner, _shares, amount); 888 | | } 889 | | 890 | | /** 891 | | * burn shares corresponding to `depositId` 892 | | * @param depositId `depositId` to burn 893 | | */ 894 | * | function _burn(uint256 depositId) internal { 895 | * | EnumerableSet.remove( 896 | * | userDeposits[depositInfo[depositId].owner], 897 | * | depositId 898 | | ); 899 | * | totalShares = totalShares - depositInfo[depositId].shares; 900 | * | delete depositInfo[depositId]; 901 | | } 902 | | 903 | | /** 904 | | * @notice 905 | | * update the market price from gmx dataStore contract at the moment of gmx callback 906 | | */ 907 | * | function _updateMarketPrice() internal { 908 | * | marketPrices = gmxUtils.getMarketPrices(market); 909 | | } 910 | | 911 | | /** 912 | | * @notice 913 | | * Any excess execution fee from GMX call is not refunded to the user. 914 | | */ 915 | * | function _payExecutionFee(uint256 depositId) internal { 916 | * | bool isDeposit = (flow == FLOW.DEPOSIT); 917 | * | uint256 minExecutionFee = getExecutionGasLimit(isDeposit) * tx.gasprice; 918 | | 919 | * | require(msg.value >= minExecutionFee, "insufficient execution fee"); 920 | * | if (msg.value > 0) { 921 | * | payable(address(gmxUtils)).transfer(msg.value); 922 | * | depositInfo[depositId].executionFee = msg.value; 923 | | } 924 | | } 925 | | 926 | | /** 927 | | * @notice Calculates the total value of the vault in terms of collateral token. 928 | | * @param prices GMX price data of market tokens from GMX API call. 929 | | * @return The total value of the vault in terms of collateral token. 930 | | */ 931 | * | function _totalAmount( 932 | | MarketPrices memory prices 933 | * | ) internal view returns (uint256) { 934 | * | IGmxUtils.PositionData memory positionData = gmxUtils.getPositionInfo( 935 | * | curPositionKey, 936 | * | prices 937 | | ); 938 | * | uint256 total = (IERC20(indexToken).balanceOf(address(this)) * 939 | * | prices.indexTokenPrice.min) / 940 | * | prices.shortTokenPrice.min + 941 | * | collateralToken.balanceOf(address(this)) + 942 | * | positionData.netValue / 943 | * | prices.shortTokenPrice.min; 944 | * | return total; 945 | | } 946 | | 947 | | /** 948 | | * @notice Checks if the contract has idle collateral funds that meet the minimum deposit amount. 949 | | * @return bool Returns true if the idle collateral funds are greater than or equal to the minimum deposit amount, false otherwise. 950 | | */ 951 | * | function _isFundIdle() internal view returns (bool) { 952 | * | uint256 balance = collateralToken.balanceOf(address(this)); 953 | * | if (balance >= minDepositAmount) { 954 | * | return true; 955 | | } else { 956 | * | return false; 957 | | } 958 | | } 959 | | 960 | | /** 961 | | * @notice Creates an increase position request. 962 | | * @dev We register position information with GMX peripheral contracts to open perp positions. 963 | | * This function doesn't open the position actually; it just registers the request of creating position. 964 | | * The actual opening/closing is done by a keeper of the GMX vault. 965 | | * @param _isLong If true, the position is long; if false, the position is short. 966 | | * @param _leverage The leverage value. 967 | | */ 968 | | function _createIncreasePosition( 969 | | bool _isLong, 970 | | uint256 _leverage, 971 | | uint256 acceptablePrice 972 | | ) internal virtual gmxLock { 973 | | //NOTE: changed by fuzzer 974 | | // Check available amounts to open positions 975 | | uint256 amountIn; 976 | | if (flow == FLOW.DEPOSIT) { 977 | | amountIn = depositInfo[counter].amount; 978 | | uint256 total = _totalAmount(marketPrices) - amountIn; 979 | | flowData = abi.encode(total); 980 | | } else { 981 | | amountIn = collateralToken.balanceOf(address(this)); 982 | | } 983 | | 984 | | Order.OrderType orderType = Order.OrderType.MarketIncrease; 985 | | collateralToken.safeTransfer(address(gmxUtils), amountIn); 986 | | uint256 sizeDelta = (marketPrices.shortTokenPrice.max * 987 | | amountIn * 988 | | _leverage) / BASIS_POINTS_DIVISOR; 989 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 990 | | market: market, 991 | | indexToken: indexToken, 992 | | initialCollateralToken: address(collateralToken), 993 | | swapPath: new address[](0), 994 | | isLong: _isLong, 995 | | sizeDeltaUsd: sizeDelta, 996 | | initialCollateralDeltaAmount: 0, 997 | | amountIn: amountIn, 998 | | callbackGasLimit: callbackGasLimit, 999 | | acceptablePrice: acceptablePrice, 1000 | | minOutputAmount: 0 1001 | | }); 1002 | | _gmxLock = true; 1003 | | gmxUtils.createOrder(orderType, orderData); 1004 | | } 1005 | | 1006 | | /** 1007 | | * @notice Creates a decrease position request. 1008 | | * @dev We register position information with GMX peripheral contracts to open perp positions. 1009 | | * This function doesn't close the position actually; it just registers the request of creating position. 1010 | | * The actual opening/closing is done by a keeper of the GMX vault. 1011 | | * @param collateralDeltaAmount The token amount of collateral to withdraw. 1012 | | * @param sizeDeltaInUsd The USD value of the change in position size (decimals is 30). 1013 | | * @param _isLong If true, the position is long; if false, the position is short. 1014 | | */ 1015 | | function _createDecreasePosition( 1016 | | uint256 collateralDeltaAmount, 1017 | | uint256 sizeDeltaInUsd, 1018 | | bool _isLong, 1019 | | uint256 acceptablePrice 1020 | | ) internal virtual gmxLock { 1021 | | address[] memory swapPath; 1022 | | Order.OrderType orderType = Order.OrderType.MarketDecrease; 1023 | | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey); 1024 | | if ( 1025 | | sizeDeltaInUsd == 0 || 1026 | | gmxUtils.willPositionCollateralBeSufficient( 1027 | | marketPrices, 1028 | | curPositionKey, 1029 | | market, 1030 | | _isLong, 1031 | | sizeDeltaInUsd 1032 | | ) 1033 | | ) { 1034 | | sizeDeltaInUsd = sizeInUsd; 1035 | | } 1036 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 1037 | | market: market, 1038 | | indexToken: indexToken, 1039 | | initialCollateralToken: address(collateralToken), 1040 | | swapPath: swapPath, 1041 | | isLong: _isLong, 1042 | | sizeDeltaUsd: sizeDeltaInUsd, 1043 | | initialCollateralDeltaAmount: collateralDeltaAmount, 1044 | | amountIn: 0, 1045 | | callbackGasLimit: callbackGasLimit, 1046 | | acceptablePrice: acceptablePrice, 1047 | | minOutputAmount: 0 1048 | | }); 1049 | | _gmxLock = true; 1050 | | gmxUtils.createOrder(orderType, orderData); 1051 | | } 1052 | | 1053 | | /** 1054 | | * @notice Settles all pending fees (borrowing fee, negative funding fee) against collateral 1055 | | * to process withdrawal requests correctly. 1056 | | * @dev GMX applies all pending fees against collateral when updating the position, which can 1057 | | * result that the current withdrawer suffers all fees of entire position. 1058 | | * This function calls `settle` to pay out fees against collateral so that fee deduction 1059 | | * from GMX positions is ignored in the withdrawal process. 1060 | | */ 1061 | * | function _settle() internal { 1062 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 1063 | * | market: market, 1064 | * | indexToken: indexToken, 1065 | * | initialCollateralToken: address(collateralToken), 1066 | * | swapPath: new address[](0), 1067 | * | isLong: beenLong, 1068 | * | sizeDeltaUsd: 0, 1069 | * | initialCollateralDeltaAmount: 0, 1070 | * | amountIn: 0, 1071 | * | callbackGasLimit: callbackGasLimit, 1072 | * | acceptablePrice: 0, 1073 | * | minOutputAmount: 0 1074 | | }); 1075 | * | _gmxLock = true; 1076 | * | gmxUtils.settle(orderData); 1077 | | } 1078 | | 1079 | | /** 1080 | | * @dev Swap data is an array of swap data and is passed from an off-chain script. 1081 | | * It could contain only Paraswap data, GMX swap data, or both of them. 1082 | | * If both are included, the first element of the array should always be Paraswap. 1083 | | * @param metadata Bytes array that includes swap data. 1084 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`. 1085 | | * @return completed If true, the swap action is completed; if false, the swap action will continue. 1086 | | */ 1087 | * | function _runSwap( 1088 | | bytes[] memory metadata, 1089 | | bool isCollateralToIndex 1090 | * | ) internal returns (bool completed) { 1091 | * | require(metadata.length > 0, "swap data missing"); 1092 | * | if (metadata.length == 2) { 1093 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode( 1094 | * | metadata[0], 1095 | | (PROTOCOL, bytes) 1096 | | ); 1097 | * | require(_protocol == PROTOCOL.DEX, "invalid swap data"); 1098 | * | swapProgressData.swapped = 1099 | * | swapProgressData.swapped + 1100 | * | _doDexSwap(data, isCollateralToIndex); 1101 | | 1102 | * | (_protocol, data) = abi.decode(metadata[1], (PROTOCOL, bytes)); 1103 | * | require(_protocol == PROTOCOL.GMX, "invalid swap data"); 1104 | | 1105 | * | _doGmxSwap(data, isCollateralToIndex); 1106 | * | return false; 1107 | | } else { 1108 | * | require(metadata.length == 1, "invalid swap data"); 1109 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode( 1110 | * | metadata[0], 1111 | | (PROTOCOL, bytes) 1112 | | ); 1113 | * | if (_protocol == PROTOCOL.DEX) { 1114 | | uint256 outputAmount = _doDexSwap(data, isCollateralToIndex); 1115 | | 1116 | | // update global state 1117 | | if (flow == FLOW.DEPOSIT) { 1118 | | // last `depositId` equals with `counter` because another deposit is not allowed before previous deposit is completely processed 1119 | | _mint( 1120 | | counter, 1121 | | outputAmount + swapProgressData.swapped, 1122 | | true 1123 | | ); 1124 | | } else if (flow == FLOW.WITHDRAW) { 1125 | | _handleReturn( 1126 | | outputAmount + swapProgressData.swapped, 1127 | | false, 1128 | | true 1129 | | ); 1130 | | } else { 1131 | | // in the flow of SIGNAL_CHANGE, if `isCollateralToIndex` is true, it is opening position, or closing position 1132 | | _updateState( 1133 | | !isCollateralToIndex, 1134 | | BASIS_POINTS_DIVISOR, 1135 | | isCollateralToIndex 1136 | | ); 1137 | | } 1138 | | 1139 | | return true; 1140 | | } else { 1141 | * | _doGmxSwap(data, isCollateralToIndex); 1142 | * | return false; 1143 | | } 1144 | | } 1145 | | } 1146 | | 1147 | | /** 1148 | | * @dev Executes a DEX swap using Paraswap. 1149 | | * @param data Swap transaction data. 1150 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`. 1151 | | * @return outputAmount The amount of output tokens received from the swap. 1152 | | */ 1153 | | function _doDexSwap( 1154 | | bytes memory data, 1155 | | bool isCollateralToIndex 1156 | | ) internal virtual returns (uint256 outputAmount) { 1157 | | //NOTE: changed by fuzzer 1158 | | (address to, uint256 amount, bytes memory callData) = abi.decode( 1159 | | data, 1160 | | (address, uint256, bytes) 1161 | | ); 1162 | | IERC20 inputToken; 1163 | | IERC20 outputToken; 1164 | | if (isCollateralToIndex) { 1165 | | inputToken = collateralToken; 1166 | | outputToken = IERC20(indexToken); 1167 | | } else { 1168 | | inputToken = IERC20(indexToken); 1169 | | outputToken = collateralToken; 1170 | | } 1171 | | uint256 balBefore = outputToken.balanceOf(address(this)); 1172 | | ParaSwapUtils.swap(to, callData); 1173 | | outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore; 1174 | | emit DexSwap( 1175 | | address(inputToken), 1176 | | amount, 1177 | | address(outputToken), 1178 | | outputAmount 1179 | | ); 1180 | | } 1181 | | 1182 | | /** 1183 | | * @dev Executes a GMX swap. 1184 | | * @param data Swap transaction data. 1185 | | * @param isCollateralToIndex Direction of swap. If true, swap `collateralToken` to `indexToken`. 1186 | | */ 1187 | | function _doGmxSwap( 1188 | | bytes memory data, 1189 | | bool isCollateralToIndex 1190 | | ) internal virtual { 1191 | | Order.OrderType orderType = Order.OrderType.MarketSwap; 1192 | | ( 1193 | | address[] memory gPath, 1194 | | uint256 amountIn, 1195 | | uint256 minOutputAmount 1196 | | ) = abi.decode(data, (address[], uint256, uint256)); 1197 | | swapProgressData.remaining = amountIn; 1198 | | swapProgressData.isCollateralToIndex = isCollateralToIndex; 1199 | | 1200 | | address tokenIn; 1201 | | if (isCollateralToIndex) { 1202 | | tokenIn = address(collateralToken); 1203 | | } else { 1204 | | tokenIn = address(indexToken); 1205 | | } 1206 | | IERC20(tokenIn).safeTransfer(address(gmxUtils), amountIn); 1207 | | 1208 | | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 1209 | | market: address(0), 1210 | | indexToken: address(0), 1211 | | initialCollateralToken: tokenIn, 1212 | | swapPath: gPath, 1213 | | isLong: isCollateralToIndex, // this param has no meaning in swap order, but uses it to see the swap direction 1214 | | sizeDeltaUsd: 0, 1215 | | initialCollateralDeltaAmount: 0, 1216 | | amountIn: amountIn, 1217 | | callbackGasLimit: callbackGasLimit, 1218 | | acceptablePrice: 0, 1219 | | minOutputAmount: minOutputAmount 1220 | | }); 1221 | | _gmxLock = true; 1222 | | gmxUtils.createOrder(orderType, orderData); 1223 | | } 1224 | | 1225 | | /** 1226 | | * @notice Handles the internal withdrawal process for a given deposit ID. 1227 | | * @dev This function calculates the share of the withdrawal, handles the swap if necessary, 1228 | | * and updates the position accordingly. 1229 | | * @param depositId The ID of the deposit to withdraw. 1230 | | */ 1231 | * | function _withdraw(uint256 depositId, bytes memory metadata) internal { 1232 | * | uint256 shares = depositInfo[depositId].shares; 1233 | * | require(shares > 0, "zero value"); 1234 | | 1235 | * | if (positionIsClosed) { 1236 | * | _handleReturn(0, true, false); 1237 | * | } else if (_isLongOneLeverage(beenLong, leverage)) { 1238 | | // beenLong && leverage == BASIS_POINTS_DIVISOR 1239 | * | uint256 swapAmount = (IERC20(indexToken).balanceOf(address(this)) * 1240 | * | shares) / totalShares; 1241 | * | nextAction.selector = NextActionSelector.SWAP_ACTION; 1242 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken 1243 | * | nextAction.data = abi.encode(swapAmount, false); 1244 | * | } else { 1245 | * | IGmxUtils.PositionData memory positionData = gmxUtils 1246 | * | .getPositionInfo(curPositionKey, marketPrices); 1247 | * | uint256 collateralDeltaAmount = (positionData.collateralAmount * 1248 | * | shares) / totalShares; 1249 | * | uint256 sizeDeltaInUsd = (positionData.sizeInUsd * shares) / 1250 | * | totalShares; 1251 | | // we always charge the position fee of negative price impact case. 1252 | * | uint256 feeAmount = gmxUtils.getPositionFeeUsd( 1253 | * | market, 1254 | * | sizeDeltaInUsd, 1255 | * | false 1256 | * | ) / marketPrices.shortTokenPrice.max; 1257 | * | int256 pnl = gmxUtils.getPnl( 1258 | * | curPositionKey, 1259 | * | marketPrices, 1260 | * | sizeDeltaInUsd 1261 | | ); 1262 | * | if (pnl < 0) { 1263 | * | collateralDeltaAmount = 1264 | * | collateralDeltaAmount - 1265 | * | feeAmount - 1266 | * | uint256(-pnl) / 1267 | * | marketPrices.shortTokenPrice.max; 1268 | | } else { 1269 | * | collateralDeltaAmount = collateralDeltaAmount - feeAmount; 1270 | | } 1271 | * | uint256 acceptablePrice = abi.decode(metadata, (uint256)); 1272 | * | _createDecreasePosition( 1273 | * | collateralDeltaAmount, 1274 | * | sizeDeltaInUsd, 1275 | * | beenLong, 1276 | * | acceptablePrice 1277 | | ); 1278 | | } 1279 | | } 1280 | | 1281 | | /** 1282 | | * @notice this function is an end of withdrawal flow. 1283 | | * @dev should update all necessary global state variables 1284 | | * 1285 | | * @param withdrawn amount of token withdrawn from the position 1286 | | * @param positionClosed true when position is closed completely by withdrawing all funds, or false 1287 | | */ 1288 | * | function _handleReturn( 1289 | | uint256 withdrawn, 1290 | | bool positionClosed, 1291 | | bool refundFee 1292 | * | ) internal { 1293 | * | (uint256 depositId, ) = abi.decode(flowData, (uint256, address)); 1294 | * | uint256 shares = depositInfo[depositId].shares; 1295 | * | uint256 amount; 1296 | * | if (positionClosed) { 1297 | * | amount = 1298 | * | (collateralToken.balanceOf(address(this)) * shares) / 1299 | * | totalShares; 1300 | * | } else { 1301 | * | uint256 balanceBeforeWithdrawal = collateralToken.balanceOf( 1302 | * | address(this) 1303 | * | ) - withdrawn; 1304 | * | amount = 1305 | * | withdrawn + 1306 | * | (balanceBeforeWithdrawal * shares) / 1307 | * | totalShares; 1308 | | } 1309 | * | if (amount > 0) { 1310 | * | _transferToken(depositId, amount); 1311 | | } 1312 | * | emit Burned( 1313 | * | depositId, 1314 | * | depositInfo[depositId].recipient, 1315 | * | depositInfo[depositId].shares, 1316 | * | amount 1317 | | ); 1318 | * | _burn(depositId); 1319 | | 1320 | * | if (refundFee) { 1321 | | uint256 usedFee = callbackGasLimit * tx.gasprice; 1322 | | if (depositInfo[depositId].executionFee > usedFee) { 1323 | | IGmxUtils(gmxUtils).refundExecutionFee( 1324 | | depositInfo[depositId].owner, 1325 | | depositInfo[depositId].executionFee - usedFee 1326 | | ); 1327 | | } 1328 | | } 1329 | | 1330 | | // update global state 1331 | * | delete swapProgressData; 1332 | * | delete flowData; 1333 | * | flow = FLOW.NONE; 1334 | | } 1335 | | 1336 | | /** 1337 | | * @dev Collect fee from the withdraw amount and transfer tokens to the user. 1338 | | * Collect fee only when the user got the profit. 1339 | | */ 1340 | * | function _transferToken(uint256 depositId, uint256 amount) internal { 1341 | * | uint256 fee; 1342 | * | if (amount > depositInfo[depositId].amount) { 1343 | * | fee = 1344 | * | ((amount - depositInfo[depositId].amount) * governanceFee) / 1345 | | BASIS_POINTS_DIVISOR; 1346 | | } 1347 | * | if (fee > 0) { 1348 | * | collateralToken.safeTransfer(treasury, fee); 1349 | | } 1350 | | 1351 | * | try 1352 | * | collateralToken.transfer( 1353 | * | depositInfo[depositId].recipient, 1354 | * | amount - fee 1355 | | ) 1356 | | {} catch { 1357 | | collateralToken.transfer(treasury, amount - fee); 1358 | | emit TokenTranferFailed( 1359 | | depositInfo[depositId].recipient, 1360 | | amount - fee 1361 | | ); 1362 | | } 1363 | * | totalDepositAmount -= depositInfo[depositId].amount; 1364 | | 1365 | * | emit FeeCollected(address(collateralToken), fee); 1366 | | } 1367 | | 1368 | | /** 1369 | | * update global state in every steps of signal change action 1370 | | * @param _positionIsClosed flag whether position is closed or not 1371 | | * @param _leverage leverage value 1372 | | * @param _isLong isLong value 1373 | | */ 1374 | * | function _updateState( 1375 | | bool _positionIsClosed, 1376 | | uint256 _leverage, 1377 | | bool _isLong 1378 | | ) internal { 1379 | * | if (flow == FLOW.SIGNAL_CHANGE) { 1380 | * | positionIsClosed = _positionIsClosed; 1381 | * | if (_positionIsClosed == false) { 1382 | * | leverage = _leverage; 1383 | * | beenLong = _isLong; 1384 | | } 1385 | * | emit SignalChanged(!_positionIsClosed, _isLong, _leverage); 1386 | | } 1387 | | 1388 | * | if (nextAction.selector == NextActionSelector.NO_ACTION) { 1389 | * | delete flowData; 1390 | * | flow = FLOW.NONE; 1391 | | } 1392 | * | delete swapProgressData; 1393 | | } 1394 | | 1395 | * | function _finalize(bytes memory data) internal { 1396 | * | if (flow == FLOW.WITHDRAW) { 1397 | * | ( 1398 | * | uint256 prevCollateralBalance, 1399 | * | bool positionClosed, 1400 | * | bool refundFee 1401 | * | ) = abi.decode(data, (uint256, bool, bool)); 1402 | * | uint256 withdrawn = collateralToken.balanceOf(address(this)) - 1403 | * | prevCollateralBalance; 1404 | * | _handleReturn(withdrawn, positionClosed, refundFee); 1405 | | } else { 1406 | * | delete swapProgressData; 1407 | * | delete flowData; 1408 | * | flow = FLOW.NONE; 1409 | | } 1410 | | } 1411 | | 1412 | | /** 1413 | | * @notice Checks if the position is a long position with 1x leverage. 1414 | | * @param _isLong If true, the position is a 1x long position. 1415 | | * @param _leverage The leverage value to check. 1416 | | * @return bool Returns true if the position is a long position with 1x leverage, false otherwise. 1417 | | */ 1418 | * | function _isLongOneLeverage( 1419 | | bool _isLong, 1420 | | uint256 _leverage 1421 | * | ) internal pure returns (bool) { 1422 | * | return _isLong && _leverage == BASIS_POINTS_DIVISOR; 1423 | | } 1424 | | 1425 | | /** 1426 | | * @notice 1427 | | * check available liquidity before create positions 1428 | | */ 1429 | | // function _checkPool(bool _isLong, address _indexToken, address _tokenIn, uint256 sizeDelta) internal view {} 1430 | | } 1431 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/PerpetualVaultLens.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 4 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | | import "./PerpetualVault.sol"; 6 | | import {MockParaSwapUtils} from "./MockParaswapUtils.sol"; 7 | | import "./interfaces/IGmxUtils.sol"; 8 | | 9 | * | contract PerpetualVaultLens is PerpetualVault, MockParaSwapUtils { 10 | | using SafeERC20 for IERC20; 11 | | 12 | | //@audit ADDED FUZZING VAR 13 | * | bool public cancellationTriggered; 14 | | 15 | * | function _getSwapProgress() public returns (uint, uint) { 16 | * | uint swappedData = swapProgressData.swapped; 17 | * | uint remainingData = swapProgressData.remaining; 18 | | } 19 | | 20 | * | function _getGMXLock() public returns (bool) { 21 | * | return _gmxLock; 22 | | } 23 | | 24 | | function getGmxUtilsAddress() public view returns (address) { 25 | | return address(gmxUtils); 26 | | } 27 | | function getRequestKey(address vault) public returns (bytes32) { 28 | | (bytes32 requestKey, , , ) = IGmxUtils( 29 | | payable(PerpetualVaultLens(vault).getGmxUtilsAddress()) 30 | | ).queue(); 31 | | } 32 | | 33 | * | function checkForCleanStart() public view returns (bool) { 34 | * | return (uint(nextAction.selector) == 0 && 35 | * | cancellationTriggered == false); //NOTE: wasn't cancelled for any reason 36 | | } 37 | | 38 | * | function run( 39 | | bool isOpen, 40 | | bool isLong, 41 | | uint256 _leverage, 42 | | MarketPrices memory prices, 43 | | bytes[] memory _swapData 44 | * | ) public override nonReentrant noneFlow onlyKeeper { 45 | * | bool success = _run(isOpen, isLong, _leverage, prices, _swapData); 46 | * | require(success, "run failed"); 47 | | } 48 | | 49 | * | function _run( 50 | | bool isOpen, 51 | | bool isLong, 52 | | uint256 _leverage, 53 | | MarketPrices memory prices, 54 | | bytes[] memory metadata 55 | * | ) internal returns (bool success) { 56 | * | require( 57 | * | address(gmxUtils).balance > minEth, 58 | | "lower than minimum eth balance" 59 | | ); 60 | * | cancellationTriggered = false; //NOTE: added by fuzzer 61 | | 62 | * | flow = FLOW.SIGNAL_CHANGE; 63 | * | flowData = abi.encode(_leverage, msg.sender); 64 | * | marketPrices = prices; 65 | | 66 | * | if (isOpen) { 67 | * | if (positionIsClosed) { 68 | * | require(_isFundIdle(), "insufficient balance to open position"); 69 | * | if (_isLongOneLeverage(isLong, _leverage)) { 70 | * | _runSwap(metadata, true); 71 | * | } else { 72 | | 73 | * | uint256 acceptablePrice = abi.decode( 74 | * | metadata[0], 75 | | (uint256) 76 | | ); 77 | * | _createIncreasePosition(isLong, _leverage, acceptablePrice); 78 | | } 79 | | } else { 80 | * | if (beenLong == isLong) { 81 | * | revert("no action needed"); 82 | | } else { 83 | | // Close current position first and then open the requested position in the next action 84 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION; 85 | * | nextAction.data = abi.encode(isLong, _leverage); 86 | * | if (_isLongOneLeverage(beenLong, leverage)) { 87 | * | _runSwap(metadata, false); 88 | * | } else { 89 | * | uint256 acceptablePrice = abi.decode( 90 | * | metadata[0], 91 | | (uint256) 92 | | ); 93 | * | _createDecreasePosition( 94 | * | 0, 95 | * | 0, 96 | * | beenLong, 97 | * | acceptablePrice 98 | | ); 99 | | } 100 | | } 101 | | } 102 | | } else { 103 | * | if (positionIsClosed == false) { 104 | * | if (_isLongOneLeverage(beenLong, leverage)) { 105 | * | _runSwap(metadata, false); 106 | * | } else { 107 | * | uint256 acceptablePrice = abi.decode( 108 | * | metadata[0], 109 | | (uint256) 110 | | ); 111 | * | _createDecreasePosition(0, 0, beenLong, acceptablePrice); 112 | | } 113 | | } else { 114 | * | revert("no action needed"); 115 | | } 116 | | } 117 | * | return true; //NOTE: added by fuzzer 118 | | } 119 | | 120 | * | function runNextAction( 121 | | MarketPrices memory prices, 122 | | bytes[] memory _swapData 123 | * | ) external override nonReentrant gmxLock onlyKeeper { 124 | * | bool success = _runNextAction(prices, _swapData); 125 | * | require(success, "runNextAction failed"); 126 | | } 127 | | 128 | * | function _runNextAction( 129 | | MarketPrices memory prices, 130 | | bytes[] memory metadata 131 | * | ) internal returns (bool success) { 132 | * | cancellationTriggered = false; 133 | | 134 | * | marketPrices = prices; 135 | * | Action memory _nextAction = nextAction; 136 | * | delete nextAction; 137 | | 138 | | 139 | * | if (_nextAction.selector == NextActionSelector.INCREASE_ACTION) { 140 | * | (bool _isLong, uint256 _leverage) = abi.decode( 141 | * | _nextAction.data, 142 | | (bool, uint256) 143 | | ); 144 | * | if (_isLongOneLeverage(_isLong, _leverage)) { 145 | * | _runSwap(metadata, true); 146 | * | } else { 147 | | // swap indexToken that could be generated from the last action into collateralToken 148 | | // use only DexSwap 149 | * | if (metadata[1].length > 0) { 150 | * | (PROTOCOL _protocol, bytes memory data) = abi.decode( 151 | | // metadata[0], 152 | * | metadata[1], //@audit changed by fuzzer 153 | | (PROTOCOL, bytes) 154 | | ); 155 | * | require(_protocol == PROTOCOL.DEX, "invalid metadata"); 156 | * | _doDexSwap(data, false); 157 | | } 158 | * | uint256 acceptablePrice = abi.decode(metadata[0], (uint256)); 159 | * | _createIncreasePosition(_isLong, _leverage, acceptablePrice); 160 | | } 161 | * | } else if (_nextAction.selector == NextActionSelector.WITHDRAW_ACTION) { 162 | | // swap indexToken that could be generated from settle action into collateralToken 163 | | // use only DexSwap 164 | * | if (metadata[1].length > 0) { 165 | | (PROTOCOL _protocol, bytes memory data) = abi.decode( 166 | | // metadata[0], 167 | | metadata[1], //@audit changed by fuzzer 168 | | (PROTOCOL, bytes) 169 | | ); 170 | | require(_protocol == PROTOCOL.DEX, "invalid metadata"); 171 | | _doDexSwap(data, false); 172 | | } 173 | * | (uint256 depositId, ) = abi.decode(flowData, (uint256, address)); 174 | | 175 | * | _withdraw(depositId, metadata[0]); 176 | * | } else if (_nextAction.selector == NextActionSelector.SWAP_ACTION) { 177 | * | (, bool isCollateralToIndex) = abi.decode( 178 | * | _nextAction.data, 179 | | (uint256, bool) 180 | | ); 181 | * | _runSwap(metadata, isCollateralToIndex); 182 | * | } else if (_nextAction.selector == NextActionSelector.SETTLE_ACTION) { 183 | * | _settle(); 184 | * | } else if (_nextAction.selector == NextActionSelector.FINALIZE) { 185 | * | if (metadata.length > 0) { 186 | | 187 | * | _runSwap(metadata, false); 188 | | } 189 | * | _finalize(_nextAction.data); 190 | * | } else if (positionIsClosed == false && _isFundIdle()) { 191 | | 192 | * | flow = FLOW.COMPOUND; 193 | * | if (_isLongOneLeverage(beenLong, leverage)) { 194 | * | _runSwap(metadata, true); 195 | * | } else { 196 | * | uint256 acceptablePrice = abi.decode(metadata[0], (uint256)); 197 | * | _createIncreasePosition(beenLong, leverage, acceptablePrice); 198 | | } 199 | | } 200 | * | return true; 201 | | } 202 | | 203 | * | function deposit( 204 | | uint256 amount 205 | * | ) public payable override nonReentrant noneFlow { 206 | | /** INSERTION BY FUZZER*/ 207 | * | _updateMarketPrice(); 208 | | /** INSERTION BY FUZZER*/ 209 | | 210 | * | bool success = _deposit(amount); 211 | * | require(success, "deposit failed"); 212 | | } 213 | | 214 | * | function _deposit(uint256 amount) internal returns (bool success) { 215 | * | require(depositPaused == false, "paused"); 216 | * | cancellationTriggered = false; 217 | * | flow = FLOW.DEPOSIT; 218 | | // flowData = abi.encode(msg.sender); 219 | * | require(amount >= minDepositAmount, "insufficient amount"); 220 | * | require( 221 | * | totalDepositAmount + amount <= maxDepositAmount, 222 | | "exceeds max deposit cap" 223 | | ); 224 | * | collateralToken.safeTransferFrom(msg.sender, address(this), amount); 225 | * | counter++; 226 | * | depositInfo[counter] = DepositInfo( 227 | * | amount, 228 | * | 0, 229 | * | msg.sender, 230 | * | 0, 231 | * | block.timestamp, 232 | * | address(0) 233 | | ); 234 | * | totalDepositAmount += amount; 235 | * | EnumerableSet.add(userDeposits[msg.sender], counter); 236 | | 237 | * | if (positionIsClosed) { 238 | * | _mint(counter, amount, false); 239 | * | _finalize(hex""); 240 | | } else { 241 | * | _payExecutionFee(counter); 242 | | // mint share token in the NextAction to involve off-chain price data and improve security 243 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION; 244 | * | nextAction.data = abi.encode(beenLong, leverage); 245 | | } 246 | * | return true; 247 | | } 248 | | 249 | * | function withdraw( 250 | | address recipient, 251 | | uint256 depositId 252 | * | ) public payable override nonReentrant noneFlow { 253 | * | bool success = _withdrawFromGamma(recipient, depositId); 254 | | } 255 | | 256 | * | function _withdrawFromGamma( 257 | | address recipient, 258 | | uint256 depositId 259 | * | ) internal returns (bool success) { 260 | * | cancellationTriggered = false; 261 | | 262 | * | flow = FLOW.WITHDRAW; 263 | * | flowData = abi.encode(depositId, msg.sender); 264 | | 265 | * | require(recipient != address(0), "zero address"); 266 | * | require( 267 | * | depositInfo[depositId].timestamp + lockTime < block.timestamp, 268 | | "locked" 269 | | ); 270 | * | require( 271 | * | EnumerableSet.contains(userDeposits[msg.sender], depositId), 272 | | "not a valid user" 273 | | ); 274 | * | require(depositInfo[depositId].shares > 0, "zero share value"); 275 | | 276 | * | depositInfo[depositId].recipient = recipient; 277 | * | if (curPositionKey != bytes32(0)) { 278 | * | _payExecutionFee(depositId); 279 | * | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 280 | * | _settle(); // Settles any outstanding fees and updates state before processing withdrawal 281 | | } else { 282 | * | _withdraw(depositId, hex"00"); 283 | | } 284 | | 285 | * | return true; 286 | | } 287 | | 288 | * | function _doDexSwap( 289 | | bytes memory data, 290 | | bool isCollateralToIndex 291 | * | ) internal override returns (uint256 outputAmount) { 292 | * | (address to, uint256 amount, bytes memory callData) = abi.decode( 293 | * | data, 294 | | (address, uint256, bytes) 295 | | ); 296 | * | IERC20 inputToken; 297 | * | IERC20 outputToken; 298 | * | if (isCollateralToIndex) { 299 | | inputToken = collateralToken; 300 | | outputToken = IERC20(indexToken); 301 | | } else { 302 | * | inputToken = IERC20(indexToken); 303 | * | outputToken = collateralToken; 304 | | } 305 | * | uint256 balBefore = outputToken.balanceOf(address(this)); 306 | * | swap(to, callData); 307 | * | outputAmount = IERC20(outputToken).balanceOf(address(this)) - balBefore; 308 | * | emit DexSwap( 309 | * | address(inputToken), 310 | * | amount, 311 | * | address(outputToken), 312 | * | outputAmount 313 | | ); 314 | | } 315 | | 316 | * | function _createIncreasePosition( 317 | | bool _isLong, 318 | | uint256 _leverage, 319 | | uint256 acceptablePrice 320 | * | ) internal override gmxLock { 321 | | // Check available amounts to open positions 322 | * | uint256 amountIn; 323 | * | if (flow == FLOW.DEPOSIT) { 324 | * | amountIn = depositInfo[counter].amount; 325 | * | uint256 total = _totalAmount(marketPrices) - amountIn; 326 | * | flowData = abi.encode(total); 327 | | } else { 328 | * | amountIn = collateralToken.balanceOf(address(this)); 329 | | } 330 | | 331 | * | Order.OrderType orderType = Order.OrderType.MarketIncrease; 332 | * | collateralToken.safeTransfer(address(gmxUtils), amountIn); 333 | * | uint256 sizeDelta = (marketPrices.shortTokenPrice.max * 334 | * | amountIn * 335 | * | _leverage) / BASIS_POINTS_DIVISOR; 336 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 337 | * | market: market, 338 | * | indexToken: indexToken, 339 | * | initialCollateralToken: address(collateralToken), 340 | * | swapPath: new address[](0), 341 | * | isLong: _isLong, 342 | * | sizeDeltaUsd: sizeDelta, 343 | * | initialCollateralDeltaAmount: 0, 344 | * | amountIn: amountIn, 345 | * | callbackGasLimit: callbackGasLimit, 346 | * | acceptablePrice: acceptablePrice, 347 | * | minOutputAmount: 0 348 | | }); 349 | * | _gmxLock = true; 350 | | 351 | * | try gmxUtils.createOrder(orderType, orderData) {} catch { 352 | * | cancellationTriggered = true; 353 | * | require(cancellationTriggered == false, "Order creation failed"); 354 | | } 355 | | } 356 | | 357 | * | function _createDecreasePosition( 358 | | uint256 collateralDeltaAmount, 359 | | uint256 sizeDeltaInUsd, 360 | | bool _isLong, 361 | | uint256 acceptablePrice 362 | * | ) internal override gmxLock { 363 | * | address[] memory swapPath; 364 | * | Order.OrderType orderType = Order.OrderType.MarketDecrease; 365 | * | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey); 366 | * | if ( 367 | * | sizeDeltaInUsd == 0 || 368 | * | gmxUtils.willPositionCollateralBeSufficient( 369 | * | marketPrices, 370 | * | curPositionKey, 371 | * | market, 372 | * | _isLong, 373 | * | sizeDeltaInUsd 374 | | ) 375 | | ) { 376 | * | sizeDeltaInUsd = sizeInUsd; 377 | | } 378 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 379 | * | market: market, 380 | * | indexToken: indexToken, 381 | * | initialCollateralToken: address(collateralToken), 382 | * | swapPath: swapPath, 383 | * | isLong: _isLong, 384 | * | sizeDeltaUsd: sizeDeltaInUsd, 385 | * | initialCollateralDeltaAmount: collateralDeltaAmount, 386 | * | amountIn: 0, 387 | * | callbackGasLimit: callbackGasLimit, 388 | * | acceptablePrice: acceptablePrice, 389 | * | minOutputAmount: 0 390 | | }); 391 | * | _gmxLock = true; 392 | | 393 | * | try gmxUtils.createOrder(orderType, orderData) {} catch { 394 | * | cancellationTriggered = true; 395 | * | require(cancellationTriggered == false, "Order creation failed"); 396 | | } 397 | | } 398 | | 399 | * | function _doGmxSwap( 400 | | bytes memory data, 401 | | bool isCollateralToIndex 402 | * | ) internal override { 403 | * | Order.OrderType orderType = Order.OrderType.MarketSwap; 404 | * | ( 405 | * | address[] memory gPath, 406 | * | uint256 amountIn, 407 | * | uint256 minOutputAmount 408 | * | ) = abi.decode(data, (address[], uint256, uint256)); 409 | * | swapProgressData.remaining = amountIn; 410 | * | swapProgressData.isCollateralToIndex = isCollateralToIndex; 411 | | 412 | * | address tokenIn; 413 | * | if (isCollateralToIndex) { 414 | * | tokenIn = address(collateralToken); 415 | | } else { 416 | * | tokenIn = address(indexToken); 417 | | } 418 | * | IERC20(tokenIn).safeTransfer(address(gmxUtils), amountIn); 419 | | 420 | * | IGmxUtils.OrderData memory orderData = IGmxUtils.OrderData({ 421 | * | market: address(0), 422 | * | indexToken: address(0), 423 | * | initialCollateralToken: tokenIn, 424 | * | swapPath: gPath, 425 | * | isLong: isCollateralToIndex, // this param has no meaning in swap order, but uses it to see the swap direction 426 | * | sizeDeltaUsd: 0, 427 | * | initialCollateralDeltaAmount: 0, 428 | * | amountIn: amountIn, 429 | * | callbackGasLimit: callbackGasLimit, 430 | * | acceptablePrice: 0, 431 | * | minOutputAmount: minOutputAmount 432 | | }); 433 | * | _gmxLock = true; 434 | | 435 | * | try gmxUtils.createOrder(orderType, orderData) {} catch { 436 | * | cancellationTriggered = true; 437 | | 438 | * | require(false, "Order creation failed"); 439 | | } 440 | | } 441 | | 442 | * | function afterOrderExecution( 443 | | bytes32 requestKey, 444 | | bytes32 positionKey, 445 | | IGmxUtils.OrderResultData memory orderResultData 446 | | ) external override nonReentrant { 447 | * | require(msg.sender == address(gmxUtils), "invalid caller"); 448 | * | _updateMarketPrice(); 449 | | 450 | * | _gmxLock = false; 451 | | // If the current action is `settle` 452 | * | if (orderResultData.isSettle) { 453 | * | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 454 | * | emit GmxPositionCallbackCalled(requestKey, true); 455 | | // emit Settled(positiveFundingFeeAmount, negativeFeeAmount); 456 | * | return; 457 | | } 458 | * | if (orderResultData.orderType == Order.OrderType.MarketIncrease) { 459 | * | curPositionKey = positionKey; 460 | * | if (flow == FLOW.DEPOSIT) { 461 | * | uint256 curAmount = _totalAmount(marketPrices); 462 | * | uint256 prevAmount = abi.decode(flowData, (uint256)); 463 | * | if (curAmount > prevAmount) { 464 | * | uint256 increased = (curAmount - prevAmount) / 465 | * | marketPrices.shortTokenPrice.max; 466 | * | _mint(counter, increased, false); 467 | | } 468 | * | nextAction.selector = NextActionSelector.FINALIZE; 469 | * | } else { 470 | * | uint256 _leverage; 471 | * | if (flowData.length > 0) { 472 | * | (_leverage, ) = abi.decode(flowData, (uint256, address)); 473 | | } else { 474 | * | _leverage = leverage; 475 | | } 476 | * | _updateState(false, _leverage, orderResultData.isLong); 477 | | } 478 | * | } else if ( 479 | * | orderResultData.orderType == Order.OrderType.MarketDecrease 480 | * | ) { 481 | | 482 | * | uint256 sizeInUsd = gmxUtils.getPositionSizeInUsd(curPositionKey); 483 | * | if (sizeInUsd == 0) { 484 | * | curPositionKey = bytes32(0); 485 | | } 486 | * | if (flow == FLOW.WITHDRAW) { 487 | | 488 | * | nextAction.selector = NextActionSelector.FINALIZE; 489 | * | uint256 prevCollateralBalance = collateralToken.balanceOf( 490 | * | address(this) 491 | * | ) - orderResultData.outputAmount; 492 | * | nextAction.data = abi.encode( 493 | * | prevCollateralBalance, 494 | * | sizeInUsd == 0, 495 | * | false 496 | | ); 497 | | // _handleReturn(orderResultData.outputAmount, sizeInUsd == 0, false); 498 | | } else { 499 | * | nextAction.selector = NextActionSelector.FINALIZE; 500 | * | _updateState(true, 0, false); 501 | | } 502 | * | } else if (orderResultData.orderType == Order.OrderType.MarketSwap) { 503 | | 504 | * | uint256 outputAmount = orderResultData.outputAmount; 505 | * | if (swapProgressData.isCollateralToIndex) { 506 | * | emit GmxSwap( 507 | * | address(collateralToken), 508 | * | swapProgressData.remaining, 509 | * | indexToken, 510 | * | outputAmount 511 | | ); 512 | | } else { 513 | * | emit GmxSwap( 514 | * | indexToken, 515 | * | swapProgressData.remaining, 516 | * | address(collateralToken), 517 | * | outputAmount 518 | | ); 519 | | } 520 | | 521 | * | if (flow == FLOW.DEPOSIT) { 522 | * | _mint(counter, outputAmount + swapProgressData.swapped, false); 523 | * | _finalize(hex""); 524 | * | } else if (flow == FLOW.WITHDRAW) { 525 | * | _handleReturn( 526 | * | outputAmount + swapProgressData.swapped, 527 | * | false, 528 | * | false 529 | | ); 530 | | } else { 531 | | // Same as if (flow == FLOW.SIGNAL_CHANGE || FLOW.COMPOUND) 532 | * | if (orderResultData.outputToken == indexToken) { 533 | * | _updateState(false, BASIS_POINTS_DIVISOR, true); 534 | | } else { 535 | * | _updateState(true, 0, false); 536 | | } 537 | | } 538 | | } 539 | * | cancellationTriggered = false; 540 | | 541 | * | emit GmxPositionCallbackCalled(requestKey, true); 542 | | // Consider emitting an event that shows the current leverage value later 543 | | } 544 | | 545 | * | function afterOrderCancellation( 546 | | bytes32 requestKey, 547 | | Order.OrderType orderType, 548 | | IGmxUtils.OrderResultData memory orderResultData 549 | | ) external override { 550 | * | require(msg.sender == address(gmxUtils), "invalid caller"); 551 | * | _gmxLock = false; 552 | * | if (orderResultData.isSettle) { 553 | | // Retry settle action. 554 | * | nextAction.selector = NextActionSelector.SETTLE_ACTION; 555 | * | } else if (orderType == Order.OrderType.MarketSwap) { 556 | | // If GMX swap fails, retry in the next action. 557 | * | nextAction.selector = NextActionSelector.SWAP_ACTION; 558 | | // abi.encode(swapAmount, swapDirection): if swap direction is true, swap collateralToken to indexToken 559 | * | nextAction.data = abi.encode( 560 | * | swapProgressData.remaining, 561 | * | swapProgressData.isCollateralToIndex 562 | | ); 563 | | } else { 564 | * | if (flow == FLOW.DEPOSIT) { 565 | * | nextAction.selector = NextActionSelector.INCREASE_ACTION; 566 | * | nextAction.data = abi.encode(beenLong, leverage); 567 | * | } else if (flow == FLOW.WITHDRAW) { 568 | | nextAction.selector = NextActionSelector.WITHDRAW_ACTION; 569 | | } else { 570 | | // If signal change fails, the offchain script starts again from the current status. 571 | * | delete flowData; 572 | * | flow = FLOW.NONE; 573 | | } 574 | | } 575 | * | cancellationTriggered = true; 576 | | 577 | * | emit GmxPositionCallbackCalled(requestKey, false); 578 | | } 579 | | } 580 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/IGmxUtils.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "../interfaces/gmx/IReader.sol"; 5 | | 6 | | interface IGmxUtils { 7 | | struct PositionData { 8 | | uint256 sizeInUsd; 9 | | uint256 sizeInTokens; 10 | | uint256 collateralAmount; 11 | | uint256 netValue; 12 | | bool isLong; 13 | | } 14 | | 15 | | struct OrderData { 16 | | address market; 17 | | address indexToken; 18 | | address initialCollateralToken; 19 | | address[] swapPath; 20 | | bool isLong; 21 | | uint256 sizeDeltaUsd; 22 | | uint256 initialCollateralDeltaAmount; 23 | | uint256 amountIn; 24 | | uint256 callbackGasLimit; 25 | | uint256 acceptablePrice; 26 | | uint256 minOutputAmount; 27 | | } 28 | | 29 | | struct OrderResultData { 30 | | Order.OrderType orderType; 31 | | bool isLong; 32 | | uint256 sizeDeltaUsd; 33 | | address outputToken; 34 | | uint256 outputAmount; 35 | | bool isSettle; 36 | | } 37 | | 38 | | function getMarket( 39 | | address market 40 | | ) external view returns (MarketProps memory); 41 | | function getPositionInfo( 42 | | bytes32 key, 43 | | MarketPrices memory prices 44 | | ) external view returns (PositionData memory); 45 | | function getPnl( 46 | | bytes32 key, 47 | | MarketPrices memory prices, 48 | | uint256 sizeDeltaUsd 49 | | ) external view returns (int256); 50 | | function getPositionFeeUsd( 51 | | address market, 52 | | uint256 sizeDeltaUsd, 53 | | bool forPositiveImpact 54 | | ) external view returns (uint256); 55 | | function getMarketPrices( 56 | | address market 57 | | ) external view returns (MarketPrices memory); 58 | | function getPositionSizeInUsd( 59 | | bytes32 key 60 | | ) external view returns (uint256 sizeInUsd); 61 | | function getExecutionGasLimit( 62 | | Order.OrderType orderType, 63 | | uint256 callbackGasLimit 64 | | ) external view returns (uint256 executionGasLimit); 65 | | function setPerpVault(address perpVault) external; 66 | | function createOrder( 67 | | Order.OrderType orderType, 68 | | OrderData memory orderData 69 | | ) external returns (bytes32); 70 | | function createOrder( 71 | | Order.OrderType orderType, 72 | | IGmxUtils.OrderData memory orderData, 73 | | MarketPrices memory prices, 74 | | bytes memory callbackdata 75 | | ) external returns (bytes32); 76 | | function settle(OrderData memory orderData) external returns (bytes32); 77 | | function cancelOrder() external; 78 | | function claimCollateralRebates( 79 | | address[] memory, 80 | | address[] memory, 81 | | uint256[] memory, 82 | | address 83 | | ) external; 84 | | function refundExecutionFee(address caller, uint256 amount) external; 85 | | function withdrawEth() external returns (uint256); 86 | | function willPositionCollateralBeSufficient( 87 | | MarketPrices memory prices, 88 | | bytes32 positionKey, 89 | | address market, 90 | | bool isLong, 91 | | uint256 sizeDeltaUsd 92 | | ) external view returns (bool); 93 | | 94 | | function queue() 95 | | external 96 | | view 97 | | returns (bytes32, address, uint256, bytes memory); //NOTE: added by fuzzer 98 | | } 99 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/IPerpetualVault.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "./IGmxUtils.sol"; 5 | | import "../libraries/Order.sol"; 6 | | 7 | | interface IPerpetualVault { 8 | | function deposit(uint256 amount) external; 9 | | function withdraw(address recipient, uint256 amount) external; 10 | | function shares(address account) external view returns (uint256); 11 | | function lookback() external view returns (uint256); 12 | | function name() external view returns (string memory); 13 | | function indexToken() external view returns (address); 14 | | function collateralToken() external view returns (address); 15 | | function isLong() external view returns (bool); 16 | | function isNextAction() external view returns (bool); 17 | | function isLock() external view returns (bool); 18 | | function isBusy() external view returns (bool); 19 | | function claimCollateralRebates(uint256[] memory) external; 20 | | function afterOrderExecution(bytes32 requestKey, bytes32 positionKey, IGmxUtils.OrderResultData memory) external; 21 | | function afterOrderCancellation(bytes32 key, Order.OrderType, IGmxUtils.OrderResultData memory) external; 22 | | } 23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IDataStore.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | interface IDataStore { 6 | | function getUint(bytes32 key) external view returns (uint256); 7 | | function getBool(bytes32 key) external view returns (bool); 8 | | function getAddress(bytes32 key) external view returns (address); 9 | | function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory); 10 | | } 11 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IExchangeRouter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | import "../../libraries/StructData.sol"; 6 | | 7 | | interface IExchangeRouter { 8 | | function sendWnt(address receiver, uint256 amount) external payable; 9 | | function sendTokens( 10 | | address token, 11 | | address receiver, 12 | | uint256 amount 13 | | ) external payable; 14 | | function createOrder( 15 | | CreateOrderParams calldata params 16 | | ) external payable returns (bytes32); 17 | | function createOrderFUZZ( 18 | | CreateOrderParams calldata params 19 | | ) external payable returns (bool, bytes32); 20 | | function cancelOrder(bytes32 key) external payable; 21 | | function claimFundingFees( 22 | | address[] memory markets, 23 | | address[] memory tokens, 24 | | address receiver 25 | | ) external returns (uint256[] memory); 26 | | function claimCollateral( 27 | | address[] memory markets, 28 | | address[] memory tokens, 29 | | uint256[] memory timeKeys, 30 | | address receiver 31 | | ) external returns (uint256[] memory); 32 | | } 33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IOrderCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | import "../../libraries/Order.sol"; 6 | | 7 | | struct EventLogData { 8 | | AddressItems addressItems; 9 | | UintItems uintItems; 10 | | IntItems intItems; 11 | | BoolItems boolItems; 12 | | Bytes32Items bytes32Items; 13 | | BytesItems bytesItems; 14 | | StringItems stringItems; 15 | | } 16 | | 17 | | struct AddressItems { 18 | | AddressKeyValue[] items; 19 | | AddressArrayKeyValue[] arrayItems; 20 | | } 21 | | 22 | | struct UintItems { 23 | | UintKeyValue[] items; 24 | | UintArrayKeyValue[] arrayItems; 25 | | } 26 | | 27 | | struct IntItems { 28 | | IntKeyValue[] items; 29 | | IntArrayKeyValue[] arrayItems; 30 | | } 31 | | 32 | | struct BoolItems { 33 | | BoolKeyValue[] items; 34 | | BoolArrayKeyValue[] arrayItems; 35 | | } 36 | | 37 | | struct Bytes32Items { 38 | | Bytes32KeyValue[] items; 39 | | Bytes32ArrayKeyValue[] arrayItems; 40 | | } 41 | | 42 | | struct BytesItems { 43 | | BytesKeyValue[] items; 44 | | BytesArrayKeyValue[] arrayItems; 45 | | } 46 | | 47 | | struct StringItems { 48 | | StringKeyValue[] items; 49 | | StringArrayKeyValue[] arrayItems; 50 | | } 51 | | 52 | | struct AddressKeyValue { 53 | | string key; 54 | | address value; 55 | | } 56 | | 57 | | struct AddressArrayKeyValue { 58 | | string key; 59 | | address[] value; 60 | | } 61 | | 62 | | struct UintKeyValue { 63 | | string key; 64 | | uint256 value; 65 | | } 66 | | 67 | | struct UintArrayKeyValue { 68 | | string key; 69 | | uint256[] value; 70 | | } 71 | | 72 | | struct IntKeyValue { 73 | | string key; 74 | | int256 value; 75 | | } 76 | | 77 | | struct IntArrayKeyValue { 78 | | string key; 79 | | int256[] value; 80 | | } 81 | | 82 | | struct BoolKeyValue { 83 | | string key; 84 | | bool value; 85 | | } 86 | | 87 | | struct BoolArrayKeyValue { 88 | | string key; 89 | | bool[] value; 90 | | } 91 | | 92 | | struct Bytes32KeyValue { 93 | | string key; 94 | | bytes32 value; 95 | | } 96 | | 97 | | struct Bytes32ArrayKeyValue { 98 | | string key; 99 | | bytes32[] value; 100 | | } 101 | | 102 | | struct BytesKeyValue { 103 | | string key; 104 | | bytes value; 105 | | } 106 | | 107 | | struct BytesArrayKeyValue { 108 | | string key; 109 | | bytes[] value; 110 | | } 111 | | 112 | | struct StringKeyValue { 113 | | string key; 114 | | string value; 115 | | } 116 | | 117 | | struct StringArrayKeyValue { 118 | | string key; 119 | | string[] value; 120 | | } 121 | | 122 | | // @title IOrderCallbackReceiver 123 | | // @dev interface for an order callback contract 124 | | interface IOrderCallbackReceiver { 125 | | // @dev called after an order execution 126 | | // @param key the key of the order 127 | | // @param order the order that was executed 128 | | function afterOrderExecution(bytes32 key, Order.Props memory order, EventLogData memory eventData) external; 129 | | 130 | | // @dev called after an order cancellation 131 | | // @param key the key of the order 132 | | // @param order the order that was cancelled 133 | | function afterOrderCancellation(bytes32 key, Order.Props memory order, EventLogData memory eventData) external; 134 | | 135 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info 136 | | // @param key the key of the order 137 | | // @param order the order that was frozen 138 | | function afterOrderFrozen(bytes32 key, Order.Props memory order, EventLogData memory eventData) external; 139 | | } 140 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IOrderHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | import "../../libraries/StructData.sol"; 6 | | 7 | | interface IOrderHandler { 8 | | function oracle() external view returns (address); 9 | | } 10 | | 11 | | interface IOracle { 12 | | function getPrimaryPrice(address token) external view returns (PriceProps memory); 13 | | } 14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/interfaces/gmx/IReader.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | import "./IDataStore.sol"; 6 | | import "../../libraries/StructData.sol"; 7 | | import "../../libraries/Position.sol"; 8 | | import "../../libraries/Order.sol"; 9 | | 10 | | interface IReader { 11 | | function getMarket(address dataStore, address key) external view returns (MarketProps memory); 12 | | // function getMarkets(IDataStore dataStore, uint256 start, uint256 end) external view returns (MarketProps[] memory); 13 | | function getPosition(address dataStore, bytes32 key) external view returns (Position.Props memory); 14 | | function getAccountOrders( 15 | | address dataStore, 16 | | address account, 17 | | uint256 start, 18 | | uint256 end 19 | | ) external view returns (Order.Props[] memory); 20 | | function getPositionInfo( 21 | | address dataStore, 22 | | address referralStorage, 23 | | bytes32 positionKey, 24 | | MarketPrices memory prices, 25 | | uint256 sizeDeltaUsd, 26 | | address uiFeeReceiver, 27 | | bool usePositionSizeAsSizeDeltaUsd 28 | | ) external view returns (PositionInfo memory); 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/Order.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | // @title Order 6 | | // @dev Struct for orders 7 | * | library Order { 8 | | using Order for Props; 9 | | 10 | | enum OrderType { 11 | | // @dev MarketSwap: swap token A to token B at the current market price 12 | | // the order will be cancelled if the minOutputAmount cannot be fulfilled 13 | | MarketSwap, 14 | | // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled 15 | | LimitSwap, 16 | | // @dev MarketIncrease: increase position at the current market price 17 | | // the order will be cancelled if the position cannot be increased at the acceptablePrice 18 | | MarketIncrease, 19 | | // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled 20 | | LimitIncrease, 21 | | // @dev MarketDecrease: decrease position at the current market price 22 | | // the order will be cancelled if the position cannot be decreased at the acceptablePrice 23 | | MarketDecrease, 24 | | // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled 25 | | LimitDecrease, 26 | | // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled 27 | | StopLossDecrease, 28 | | // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met 29 | | Liquidation 30 | | } 31 | | 32 | | // to help further differentiate orders 33 | | enum SecondaryOrderType { 34 | | None, 35 | | Adl 36 | | } 37 | | 38 | | enum DecreasePositionSwapType { 39 | | NoSwap, 40 | | SwapPnlTokenToCollateralToken, 41 | | SwapCollateralTokenToPnlToken 42 | | } 43 | | 44 | | // @dev there is a limit on the number of fields a struct can have when being passed 45 | | // or returned as a memory variable which can cause "Stack too deep" errors 46 | | // use sub-structs to avoid this issue 47 | | // @param addresses address values 48 | | // @param numbers number values 49 | | // @param flags boolean values 50 | | struct Props { 51 | | Addresses addresses; 52 | | Numbers numbers; 53 | | Flags flags; 54 | | } 55 | | 56 | | // @param account the account of the order 57 | | // @param receiver the receiver for any token transfers 58 | | // this field is meant to allow the output of an order to be 59 | | // received by an address that is different from the creator of the 60 | | // order whether this is for swaps or whether the account is the owner 61 | | // of a position 62 | | // for funding fees and claimable collateral, the funds are still 63 | | // credited to the owner of the position indicated by order.account 64 | | // @param callbackContract the contract to call for callbacks 65 | | // @param uiFeeReceiver the ui fee receiver 66 | | // @param market the trading market 67 | | // @param initialCollateralToken for increase orders, initialCollateralToken 68 | | // is the token sent in by the user, the token will be swapped through the 69 | | // specified swapPath, before being deposited into the position as collateral 70 | | // for decrease orders, initialCollateralToken is the collateral token of the position 71 | | // withdrawn collateral from the decrease of the position will be swapped 72 | | // through the specified swapPath 73 | | // for swaps, initialCollateralToken is the initial token sent for the swap 74 | | // @param swapPath an array of market addresses to swap through 75 | | struct Addresses { 76 | | address account; 77 | | address receiver; 78 | | address cancellationReceiver; 79 | | address callbackContract; 80 | | address uiFeeReceiver; 81 | | address market; 82 | | address initialCollateralToken; 83 | | address[] swapPath; 84 | | } 85 | | 86 | | // @param sizeDeltaUsd the requested change in position size 87 | | // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount 88 | | // is the amount of the initialCollateralToken sent in by the user 89 | | // for decrease orders, initialCollateralDeltaAmount is the amount of the position's 90 | | // collateralToken to withdraw 91 | | // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent 92 | | // in for the swap 93 | | // @param orderType the order type 94 | | // @param triggerPrice the trigger price for non-market orders 95 | | // @param acceptablePrice the acceptable execution price for increase / decrease orders 96 | | // @param executionFee the execution fee for keepers 97 | | // @param callbackGasLimit the gas limit for the callbackContract 98 | | // @param minOutputAmount the minimum output amount for decrease orders and swaps 99 | | // note that for decrease orders, multiple tokens could be received, for this reason, the 100 | | // minOutputAmount value is treated as a USD value for validation in decrease orders 101 | | // @param updatedAtBlock the block at which the order was last updated 102 | | struct Numbers { 103 | | OrderType orderType; 104 | | DecreasePositionSwapType decreasePositionSwapType; 105 | | uint256 sizeDeltaUsd; 106 | | uint256 initialCollateralDeltaAmount; 107 | | uint256 triggerPrice; 108 | | uint256 acceptablePrice; 109 | | uint256 executionFee; 110 | | uint256 callbackGasLimit; 111 | | uint256 minOutputAmount; 112 | | uint256 updatedAtBlock; 113 | | uint256 updatedAtTime; 114 | | } 115 | | 116 | | // @param isLong whether the order is for a long or short 117 | | // @param shouldUnwrapNativeToken whether to unwrap native tokens before 118 | | // transferring to the user 119 | | // @param isFrozen whether the order is frozen 120 | | struct Flags { 121 | | bool isLong; 122 | | bool shouldUnwrapNativeToken; 123 | | bool isFrozen; 124 | | bool autoCancel; 125 | | } 126 | | } 127 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/ParaSwapUtils.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 6 | | import {console} from "forge-std/Test.sol"; 7 | | interface IAugustusSwapper { 8 | | function getTokenTransferProxy() external view returns (address); 9 | | } 10 | | 11 | * | library ParaSwapUtils { 12 | | using SafeERC20 for IERC20; 13 | | 14 | | function swap(address to, bytes memory callData) external { 15 | | _validateCallData(to, callData); 16 | | address approvalAddress = IAugustusSwapper(to).getTokenTransferProxy(); 17 | | address fromToken; 18 | | uint256 fromAmount; 19 | | assembly { 20 | | fromToken := mload(add(callData, 68)) 21 | | fromAmount := mload(add(callData, 100)) 22 | | } 23 | | IERC20(fromToken).safeApprove(approvalAddress, fromAmount); 24 | | (bool success, ) = to.call(callData); 25 | | require(success, "paraswap call reverted"); 26 | | } 27 | | 28 | | function _validateCallData( 29 | | address to, 30 | | bytes memory callData 31 | | ) internal view { 32 | | require( 33 | | to == address(0x731a10897d267e19B34503aD902d0A29173Ba4B1), //foundry address 34 | | "invalid paraswap callee" 35 | | ); 36 | | 37 | | address receiver; 38 | | assembly { 39 | | receiver := mload(add(callData, 196)) 40 | | } 41 | | require(receiver == address(this), "invalid paraswap calldata"); 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/Position.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.4; 4 | | 5 | | // @title Position 6 | | // @dev Stuct for positions 7 | | // 8 | | // borrowing fees for position require only a borrowingFactor to track 9 | | // an example on how this works is if the global cumulativeBorrowingFactor is 10020% 10 | | // a position would be opened with borrowingFactor as 10020% 11 | | // after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would 12 | | // owe 5% of the position size as borrowing fees 13 | | // the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs 14 | | // when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's 15 | | // collateral and transferred into the LP pool 16 | | // 17 | | // the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees 18 | | // based on the fiat value of the position sizes 19 | | // 20 | | // for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position 21 | | // claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would 22 | | // only owe 0.05 longToken ($200) 23 | | // this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts 24 | | // to be deducted and to be paid out need to be tracked instead 25 | | // 26 | | // for funding fees, there are four values to consider: 27 | | // 1. long positions with market.longToken as collateral 28 | | // 2. long positions with market.shortToken as collateral 29 | | // 3. short positions with market.longToken as collateral 30 | | // 4. short positions with market.shortToken as collateral 31 | * | library Position { 32 | | // @dev there is a limit on the number of fields a struct can have when being passed 33 | | // or returned as a memory variable which can cause "Stack too deep" errors 34 | | // use sub-structs to avoid this issue 35 | | // @param addresses address values 36 | | // @param numbers number values 37 | | // @param flags boolean values 38 | | struct Props { 39 | | Addresses addresses; 40 | | Numbers numbers; 41 | | Flags flags; 42 | | } 43 | | 44 | | // @param account the position's account 45 | | // @param market the position's market 46 | | // @param collateralToken the position's collateralToken 47 | | struct Addresses { 48 | | address account; 49 | | address market; 50 | | address collateralToken; 51 | | } 52 | | 53 | | // @param sizeInUsd the position's size in USD 54 | | // @param sizeInTokens the position's size in tokens 55 | | // @param collateralAmount the amount of collateralToken for collateral 56 | | // @param borrowingFactor the position's borrowing factor 57 | | // @param fundingFeeAmountPerSize the position's funding fee per size 58 | | // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size 59 | | // for the market.longToken 60 | | // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size 61 | | // for the market.shortToken 62 | | // @param increasedAtBlock the block at which the position was last increased 63 | | // @param decreasedAtBlock the block at which the position was last decreased 64 | | struct Numbers { 65 | | uint256 sizeInUsd; 66 | | uint256 sizeInTokens; 67 | | uint256 collateralAmount; 68 | | uint256 borrowingFactor; 69 | | uint256 fundingFeeAmountPerSize; 70 | | uint256 longTokenClaimableFundingAmountPerSize; 71 | | uint256 shortTokenClaimableFundingAmountPerSize; 72 | | uint256 increasedAtBlock; 73 | | uint256 decreasedAtBlock; 74 | | uint256 increasedAtTime; 75 | | uint256 decreasedAtTime; 76 | | } 77 | | 78 | | // @param isLong whether the position is a long or short 79 | | struct Flags { 80 | | bool isLong; 81 | | } 82 | | } 83 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/StructData.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "./Position.sol"; 5 | | import "./Order.sol"; 6 | | 7 | | struct MarketProps { 8 | | address marketToken; 9 | | address indexToken; 10 | | address longToken; 11 | | address shortToken; 12 | | } 13 | | 14 | | struct PriceProps { 15 | | uint256 min; 16 | | uint256 max; 17 | | } 18 | | 19 | | struct MarketPrices { 20 | | PriceProps indexTokenPrice; 21 | | PriceProps longTokenPrice; 22 | | PriceProps shortTokenPrice; 23 | | } 24 | | 25 | | struct PositionFees { 26 | | PositionReferralFees referral; 27 | | PositionFundingFees funding; 28 | | PositionBorrowingFees borrowing; 29 | | PositionUiFees ui; 30 | | PriceProps collateralTokenPrice; 31 | | uint256 positionFeeFactor; 32 | | uint256 protocolFeeAmount; 33 | | uint256 positionFeeReceiverFactor; 34 | | uint256 feeReceiverAmount; 35 | | uint256 feeAmountForPool; 36 | | uint256 positionFeeAmountForPool; 37 | | uint256 positionFeeAmount; 38 | | uint256 totalCostAmountExcludingFunding; 39 | | uint256 totalCostAmount; 40 | | } 41 | | 42 | | // @param affiliate the referral affiliate of the trader 43 | | // @param traderDiscountAmount the discount amount for the trader 44 | | // @param affiliateRewardAmount the affiliate reward amount 45 | | struct PositionReferralFees { 46 | | bytes32 referralCode; 47 | | address affiliate; 48 | | address trader; 49 | | uint256 totalRebateFactor; 50 | | uint256 traderDiscountFactor; 51 | | uint256 totalRebateAmount; 52 | | uint256 traderDiscountAmount; 53 | | uint256 affiliateRewardAmount; 54 | | } 55 | | 56 | | struct PositionBorrowingFees { 57 | | uint256 borrowingFeeUsd; 58 | | uint256 borrowingFeeAmount; 59 | | uint256 borrowingFeeReceiverFactor; 60 | | uint256 borrowingFeeAmountForFeeReceiver; 61 | | } 62 | | 63 | | // @param fundingFeeAmount the position's funding fee amount 64 | | // @param claimableLongTokenAmount the negative funding fee in long token that is claimable 65 | | // @param claimableShortTokenAmount the negative funding fee in short token that is claimable 66 | | // @param latestLongTokenFundingAmountPerSize the latest long token funding 67 | | // amount per size for the market 68 | | // @param latestShortTokenFundingAmountPerSize the latest short token funding 69 | | // amount per size for the market 70 | | struct PositionFundingFees { 71 | | uint256 fundingFeeAmount; 72 | | uint256 claimableLongTokenAmount; 73 | | uint256 claimableShortTokenAmount; 74 | | uint256 latestFundingFeeAmountPerSize; 75 | | uint256 latestLongTokenClaimableFundingAmountPerSize; 76 | | uint256 latestShortTokenClaimableFundingAmountPerSize; 77 | | } 78 | | 79 | | struct PositionUiFees { 80 | | address uiFeeReceiver; 81 | | uint256 uiFeeReceiverFactor; 82 | | uint256 uiFeeAmount; 83 | | } 84 | | 85 | | struct ExecutionPriceResult { 86 | | int256 priceImpactUsd; 87 | | uint256 priceImpactDiffUsd; 88 | | uint256 executionPrice; 89 | | } 90 | | 91 | | struct PositionInfo { 92 | | Position.Props position; 93 | | PositionFees fees; 94 | | ExecutionPriceResult executionPriceResult; 95 | | int256 basePnlUsd; 96 | | int256 uncappedBasePnlUsd; 97 | | int256 pnlAfterPriceImpactUsd; 98 | | } 99 | | 100 | | // @param addresses address values 101 | | // @param numbers number values 102 | | // @param orderType for order.orderType 103 | | // @param decreasePositionSwapType for order.decreasePositionSwapType 104 | | // @param isLong for order.isLong 105 | | // @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken 106 | | struct CreateOrderParams { 107 | | CreateOrderParamsAddresses addresses; 108 | | CreateOrderParamsNumbers numbers; 109 | | Order.OrderType orderType; 110 | | Order.DecreasePositionSwapType decreasePositionSwapType; 111 | | bool isLong; 112 | | bool shouldUnwrapNativeToken; 113 | | bool autoCancel; 114 | | bytes32 referralCode; 115 | | } 116 | | 117 | | // @param receiver for order.receiver 118 | | // @param callbackContract for order.callbackContract 119 | | // @param market for order.market 120 | | // @param initialCollateralToken for order.initialCollateralToken 121 | | // @param swapPath for order.swapPath 122 | | struct CreateOrderParamsAddresses { 123 | | address receiver; 124 | | address cancellationReceiver; 125 | | address callbackContract; 126 | | address uiFeeReceiver; 127 | | address market; 128 | | address initialCollateralToken; 129 | | address[] swapPath; 130 | | } 131 | | 132 | | // @param sizeDeltaUsd for order.sizeDeltaUsd 133 | | // @param triggerPrice for order.triggerPrice 134 | | // @param acceptablePrice for order.acceptablePrice 135 | | // @param executionFee for order.executionFee 136 | | // @param callbackGasLimit for order.callbackGasLimit 137 | | // @param minOutputAmount for order.minOutputAmount 138 | | struct CreateOrderParamsNumbers { 139 | | uint256 sizeDeltaUsd; 140 | | uint256 initialCollateralDeltaAmount; 141 | | uint256 triggerPrice; 142 | | uint256 acceptablePrice; 143 | | uint256 executionFee; 144 | | uint256 callbackGasLimit; 145 | | uint256 minOutputAmount; 146 | | } 147 | | 148 | | // following are not from GMX. 149 | | 150 | | enum PROTOCOL { 151 | | DEX, 152 | | GMX 153 | | } 154 | | 155 | | struct lifiSwapData { 156 | | address callTo; 157 | | address approveTo; 158 | | address sendingAssetId; 159 | | address receivingAssetId; 160 | | uint256 fromAmount; 161 | | bytes callData; 162 | | bool requiresDeposit; 163 | | } 164 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/contracts/libraries/gmx/MarketUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 6 | | import "@openzeppelin/contracts/utils/math/Math.sol"; 7 | | import "@openzeppelin/contracts/utils/math/SignedSafeMath.sol"; 8 | | 9 | | import "../../interfaces/gmx/IDataStore.sol"; 10 | | import "../StructData.sol"; 11 | | 12 | | // @title MarketUtils 13 | | // @dev Library for market functions 14 | * | library MarketUtils { 15 | | using SignedSafeMath for int256; 16 | | using SafeCast for int256; 17 | | using SafeCast for uint256; 18 | | 19 | * | uint256 public constant FLOAT_PRECISION = 10 ** 30; 20 | * | bytes32 public constant OPEN_INTEREST = keccak256(abi.encode("OPEN_INTEREST")); 21 | * | bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode("MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER")); 22 | * | bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode("MIN_COLLATERAL_FACTOR")); 23 | | 24 | | struct WillPositionCollateralBeSufficientValues { 25 | | uint256 positionSizeInUsd; 26 | | uint256 positionCollateralAmount; 27 | | int256 realizedPnlUsd; 28 | | int256 openInterestDelta; 29 | | } 30 | | 31 | * | function willPositionCollateralBeSufficient( 32 | | IDataStore dataStore, 33 | | MarketProps memory market, 34 | | MarketPrices memory prices, 35 | | bool isLong, 36 | | WillPositionCollateralBeSufficientValues memory values 37 | * | ) public view returns (bool, int256) { 38 | * | PriceProps memory collateralTokenPrice = prices.shortTokenPrice; 39 | | 40 | * | int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256(); 41 | | 42 | | // deduct realized pnl if it is negative since this would be paid from 43 | | // the position's collateral 44 | * | if (values.realizedPnlUsd < 0) { 45 | * | remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd; 46 | | } 47 | | 48 | * | if (remainingCollateralUsd < 0) { 49 | | return (false, remainingCollateralUsd); 50 | | } 51 | | 52 | | // the min collateral factor will increase as the open interest for a market increases 53 | | // this may lead to previously created limit increase orders not being executable 54 | | // 55 | | // the position's pnl is not factored into the remainingCollateralUsd value, since 56 | | // factoring in a positive pnl may allow the user to manipulate price and bypass this check 57 | | // it may be useful to factor in a negative pnl for this check, this can be added if required 58 | * | uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest( 59 | * | dataStore, 60 | * | market, 61 | * | values.openInterestDelta, 62 | * | isLong 63 | | ); 64 | | 65 | * | uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken); 66 | | // use the minCollateralFactor for the market if it is larger 67 | * | if (minCollateralFactorForMarket > minCollateralFactor) { 68 | * | minCollateralFactor = minCollateralFactorForMarket; 69 | | } 70 | | 71 | * | int256 minCollateralUsdForLeverage = applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256(); 72 | * | bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage; 73 | | 74 | * | return (willBeSufficient, remainingCollateralUsd); 75 | | } 76 | | 77 | | // @dev get the min collateral factor for open interest multiplier 78 | | // @param dataStore DataStore 79 | | // @param market the market to check 80 | | // @param isLong whether it is for the long or short side 81 | * | function getMinCollateralFactorForOpenInterestMultiplier(IDataStore dataStore, address market, bool isLong) internal view returns (uint256) { 82 | * | return dataStore.getUint(minCollateralFactorForOpenInterestMultiplierKey(market, isLong)); 83 | | } 84 | | 85 | | // @dev get the min collateral factor for open interest 86 | | // @param dataStore DataStore 87 | | // @param market the market to check 88 | | // @param longToken the long token of the market 89 | | // @param shortToken the short token of the market 90 | | // @param openInterestDelta the change in open interest 91 | | // @param isLong whether it is for the long or short side 92 | * | function getMinCollateralFactorForOpenInterest( 93 | | IDataStore dataStore, 94 | | MarketProps memory market, 95 | | int256 openInterestDelta, 96 | | bool isLong 97 | * | ) internal view returns (uint256) { 98 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 99 | * | openInterest = sumReturnUint256(openInterest, openInterestDelta); 100 | * | uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong); 101 | * | return applyFactor(openInterest, multiplierFactor); 102 | | } 103 | | 104 | | // @dev get the open interest of a market 105 | | // @param dataStore DataStore 106 | | // @param market the market to check 107 | | // @param longToken the long token of the market 108 | | // @param shortToken the short token of the market 109 | | function getOpenInterest( 110 | | IDataStore dataStore, 111 | | MarketProps memory market 112 | | ) internal view returns (uint256) { 113 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true); 114 | | uint256 shortOpenInterest = getOpenInterest(dataStore, market, false); 115 | | 116 | | return longOpenInterest + shortOpenInterest; 117 | | } 118 | | 119 | | // @dev get either the long or short open interest for a market 120 | | // @param dataStore DataStore 121 | | // @param market the market to check 122 | | // @param longToken the long token of the market 123 | | // @param shortToken the short token of the market 124 | | // @param isLong whether to get the long or short open interest 125 | | // @return the long or short open interest for a market 126 | * | function getOpenInterest( 127 | | IDataStore dataStore, 128 | | MarketProps memory market, 129 | | bool isLong 130 | * | ) internal view returns (uint256) { 131 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 132 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor); 133 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor); 134 | | 135 | * | return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral; 136 | | } 137 | | 138 | | // @dev the long and short open interest for a market based on the collateral token used 139 | | // @param dataStore DataStore 140 | | // @param market the market to check 141 | | // @param collateralToken the collateral token to check 142 | | // @param isLong whether to check the long or short side 143 | * | function getOpenInterest( 144 | | IDataStore dataStore, 145 | | address market, 146 | | address collateralToken, 147 | | bool isLong, 148 | | uint256 divisor 149 | * | ) internal view returns (uint256) { 150 | * | return dataStore.getUint(openInterestKey(market, collateralToken, isLong)) / divisor; 151 | | } 152 | | 153 | | // this is used to divide the values of getPoolAmount and getOpenInterest 154 | | // if the longToken and shortToken are the same, then these values have to be divided by two 155 | | // to avoid double counting 156 | * | function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) { 157 | * | return longToken == shortToken ? 2 : 1; 158 | | } 159 | | 160 | * | function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) { 161 | * | if (b > 0) { 162 | | return a + uint256(b); 163 | | } 164 | | 165 | * | return a - uint256(-b); 166 | | } 167 | | 168 | | /** 169 | | * Applies the given factor to the given value and returns the result. 170 | | * 171 | | * @param value The value to apply the factor to. 172 | | * @param factor The factor to apply. 173 | | * @return The result of applying the factor to the value. 174 | | */ 175 | * | function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) { 176 | * | return Math.mulDiv(value, factor, FLOAT_PRECISION); 177 | | } 178 | | 179 | | // @dev get the min collateral factor 180 | | // @param dataStore DataStore 181 | | // @param market the market to check 182 | * | function getMinCollateralFactor(IDataStore dataStore, address market) internal view returns (uint256) { 183 | * | return dataStore.getUint(minCollateralFactorKey(market)); 184 | | } 185 | | 186 | | // @dev key for open interest 187 | | // @param market the market to check 188 | | // @param collateralToken the collateralToken to check 189 | | // @param isLong whether to check the long or short open interest 190 | | // @return key for open interest 191 | * | function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 192 | * | return keccak256(abi.encode( 193 | | OPEN_INTEREST, 194 | * | market, 195 | * | collateralToken, 196 | * | isLong 197 | | )); 198 | | } 199 | | 200 | | // @dev the min collateral factor for open interest multiplier key 201 | | // @param the market for the factor 202 | * | function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) { 203 | * | return keccak256(abi.encode( 204 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER, 205 | * | market, 206 | * | isLong 207 | | )); 208 | | } 209 | | 210 | | // @dev the min collateral factor key 211 | | // @param the market for the min collateral factor 212 | * | function minCollateralFactorKey(address market) internal pure returns (bytes32) { 213 | * | return keccak256(abi.encode( 214 | | MIN_COLLATERAL_FACTOR, 215 | * | market 216 | | )); 217 | | } 218 | | } 219 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Base.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | import {StdStorage} from "./StdStorage.sol"; 5 | | import {Vm, VmSafe} from "./Vm.sol"; 6 | | 7 | | abstract contract CommonBase { 8 | | // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. 9 | * | address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); 10 | | // console.sol and console2.sol work by executing a staticcall to this address. 11 | | address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; 12 | | // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. 13 | | address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; 14 | | // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. 15 | | address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); 16 | | // Address of the test contract, deployed by the DEFAULT_SENDER. 17 | | address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; 18 | | // Deterministic deployment address of the Multicall3 contract. 19 | | address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; 20 | | // The order of the secp256k1 curve. 21 | | uint256 internal constant SECP256K1_ORDER = 22 | | 115792089237316195423570985008687907852837564279074904382605163141518161494337; 23 | | 24 | | uint256 internal constant UINT256_MAX = 25 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 26 | | 27 | | Vm internal constant vm = Vm(VM_ADDRESS); 28 | | StdStorage internal stdstore; 29 | | } 30 | | 31 | | abstract contract TestBase is CommonBase {} 32 | | 33 | | abstract contract ScriptBase is CommonBase { 34 | | VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); 35 | | } 36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdAssertions.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | pragma experimental ABIEncoderV2; 4 | | 5 | | import {Vm} from "./Vm.sol"; 6 | | 7 | | abstract contract StdAssertions { 8 | * | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); 9 | | 10 | | event log(string); 11 | | event logs(bytes); 12 | | 13 | | event log_address(address); 14 | | event log_bytes32(bytes32); 15 | | event log_int(int256); 16 | | event log_uint(uint256); 17 | | event log_bytes(bytes); 18 | | event log_string(string); 19 | | 20 | | event log_named_address(string key, address val); 21 | | event log_named_bytes32(string key, bytes32 val); 22 | | event log_named_decimal_int(string key, int256 val, uint256 decimals); 23 | | event log_named_decimal_uint(string key, uint256 val, uint256 decimals); 24 | | event log_named_int(string key, int256 val); 25 | | event log_named_uint(string key, uint256 val); 26 | | event log_named_bytes(string key, bytes val); 27 | | event log_named_string(string key, string val); 28 | | 29 | | event log_array(uint256[] val); 30 | | event log_array(int256[] val); 31 | | event log_array(address[] val); 32 | | event log_named_array(string key, uint256[] val); 33 | | event log_named_array(string key, int256[] val); 34 | | event log_named_array(string key, address[] val); 35 | | 36 | | bool private _failed; 37 | | 38 | * | function failed() public view returns (bool) { 39 | * | if (_failed) { 40 | | return _failed; 41 | | } else { 42 | * | return vm.load(address(vm), bytes32("failed")) != bytes32(0); 43 | | } 44 | | } 45 | | 46 | | function fail() internal virtual { 47 | | vm.store(address(vm), bytes32("failed"), bytes32(uint256(1))); 48 | | _failed = true; 49 | | } 50 | | 51 | | function assertTrue(bool data) internal pure virtual { 52 | | vm.assertTrue(data); 53 | | } 54 | | 55 | | function assertTrue(bool data, string memory err) internal pure virtual { 56 | | vm.assertTrue(data, err); 57 | | } 58 | | 59 | | function assertFalse(bool data) internal pure virtual { 60 | | vm.assertFalse(data); 61 | | } 62 | | 63 | | function assertFalse(bool data, string memory err) internal pure virtual { 64 | | vm.assertFalse(data, err); 65 | | } 66 | | 67 | | function assertEq(bool left, bool right) internal pure virtual { 68 | | vm.assertEq(left, right); 69 | | } 70 | | 71 | | function assertEq(bool left, bool right, string memory err) internal pure virtual { 72 | | vm.assertEq(left, right, err); 73 | | } 74 | | 75 | | function assertEq(uint256 left, uint256 right) internal pure virtual { 76 | | vm.assertEq(left, right); 77 | | } 78 | | 79 | | function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual { 80 | | vm.assertEq(left, right, err); 81 | | } 82 | | 83 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 84 | | vm.assertEqDecimal(left, right, decimals); 85 | | } 86 | | 87 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { 88 | | vm.assertEqDecimal(left, right, decimals, err); 89 | | } 90 | | 91 | | function assertEq(int256 left, int256 right) internal pure virtual { 92 | | vm.assertEq(left, right); 93 | | } 94 | | 95 | | function assertEq(int256 left, int256 right, string memory err) internal pure virtual { 96 | | vm.assertEq(left, right, err); 97 | | } 98 | | 99 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 100 | | vm.assertEqDecimal(left, right, decimals); 101 | | } 102 | | 103 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 104 | | vm.assertEqDecimal(left, right, decimals, err); 105 | | } 106 | | 107 | | function assertEq(address left, address right) internal pure virtual { 108 | | vm.assertEq(left, right); 109 | | } 110 | | 111 | | function assertEq(address left, address right, string memory err) internal pure virtual { 112 | | vm.assertEq(left, right, err); 113 | | } 114 | | 115 | | function assertEq(bytes32 left, bytes32 right) internal pure virtual { 116 | | vm.assertEq(left, right); 117 | | } 118 | | 119 | | function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { 120 | | vm.assertEq(left, right, err); 121 | | } 122 | | 123 | | function assertEq32(bytes32 left, bytes32 right) internal pure virtual { 124 | | assertEq(left, right); 125 | | } 126 | | 127 | | function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { 128 | | assertEq(left, right, err); 129 | | } 130 | | 131 | | function assertEq(string memory left, string memory right) internal pure virtual { 132 | | vm.assertEq(left, right); 133 | | } 134 | | 135 | | function assertEq(string memory left, string memory right, string memory err) internal pure virtual { 136 | | vm.assertEq(left, right, err); 137 | | } 138 | | 139 | | function assertEq(bytes memory left, bytes memory right) internal pure virtual { 140 | | vm.assertEq(left, right); 141 | | } 142 | | 143 | | function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { 144 | | vm.assertEq(left, right, err); 145 | | } 146 | | 147 | | function assertEq(bool[] memory left, bool[] memory right) internal pure virtual { 148 | | vm.assertEq(left, right); 149 | | } 150 | | 151 | | function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { 152 | | vm.assertEq(left, right, err); 153 | | } 154 | | 155 | | function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual { 156 | | vm.assertEq(left, right); 157 | | } 158 | | 159 | | function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { 160 | | vm.assertEq(left, right, err); 161 | | } 162 | | 163 | | function assertEq(int256[] memory left, int256[] memory right) internal pure virtual { 164 | | vm.assertEq(left, right); 165 | | } 166 | | 167 | | function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { 168 | | vm.assertEq(left, right, err); 169 | | } 170 | | 171 | | function assertEq(address[] memory left, address[] memory right) internal pure virtual { 172 | | vm.assertEq(left, right); 173 | | } 174 | | 175 | | function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { 176 | | vm.assertEq(left, right, err); 177 | | } 178 | | 179 | | function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { 180 | | vm.assertEq(left, right); 181 | | } 182 | | 183 | | function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { 184 | | vm.assertEq(left, right, err); 185 | | } 186 | | 187 | | function assertEq(string[] memory left, string[] memory right) internal pure virtual { 188 | | vm.assertEq(left, right); 189 | | } 190 | | 191 | | function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { 192 | | vm.assertEq(left, right, err); 193 | | } 194 | | 195 | | function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual { 196 | | vm.assertEq(left, right); 197 | | } 198 | | 199 | | function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { 200 | | vm.assertEq(left, right, err); 201 | | } 202 | | 203 | | // Legacy helper 204 | | function assertEqUint(uint256 left, uint256 right) internal pure virtual { 205 | | assertEq(left, right); 206 | | } 207 | | 208 | | function assertNotEq(bool left, bool right) internal pure virtual { 209 | | vm.assertNotEq(left, right); 210 | | } 211 | | 212 | | function assertNotEq(bool left, bool right, string memory err) internal pure virtual { 213 | | vm.assertNotEq(left, right, err); 214 | | } 215 | | 216 | | function assertNotEq(uint256 left, uint256 right) internal pure virtual { 217 | | vm.assertNotEq(left, right); 218 | | } 219 | | 220 | | function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual { 221 | | vm.assertNotEq(left, right, err); 222 | | } 223 | | 224 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 225 | | vm.assertNotEqDecimal(left, right, decimals); 226 | | } 227 | | 228 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) 229 | | internal 230 | | pure 231 | | virtual 232 | | { 233 | | vm.assertNotEqDecimal(left, right, decimals, err); 234 | | } 235 | | 236 | | function assertNotEq(int256 left, int256 right) internal pure virtual { 237 | | vm.assertNotEq(left, right); 238 | | } 239 | | 240 | | function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual { 241 | | vm.assertNotEq(left, right, err); 242 | | } 243 | | 244 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 245 | | vm.assertNotEqDecimal(left, right, decimals); 246 | | } 247 | | 248 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 249 | | vm.assertNotEqDecimal(left, right, decimals, err); 250 | | } 251 | | 252 | | function assertNotEq(address left, address right) internal pure virtual { 253 | | vm.assertNotEq(left, right); 254 | | } 255 | | 256 | | function assertNotEq(address left, address right, string memory err) internal pure virtual { 257 | | vm.assertNotEq(left, right, err); 258 | | } 259 | | 260 | | function assertNotEq(bytes32 left, bytes32 right) internal pure virtual { 261 | | vm.assertNotEq(left, right); 262 | | } 263 | | 264 | | function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual { 265 | | vm.assertNotEq(left, right, err); 266 | | } 267 | | 268 | | function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual { 269 | | assertNotEq(left, right); 270 | | } 271 | | 272 | | function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual { 273 | | assertNotEq(left, right, err); 274 | | } 275 | | 276 | | function assertNotEq(string memory left, string memory right) internal pure virtual { 277 | | vm.assertNotEq(left, right); 278 | | } 279 | | 280 | | function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual { 281 | | vm.assertNotEq(left, right, err); 282 | | } 283 | | 284 | | function assertNotEq(bytes memory left, bytes memory right) internal pure virtual { 285 | | vm.assertNotEq(left, right); 286 | | } 287 | | 288 | | function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual { 289 | | vm.assertNotEq(left, right, err); 290 | | } 291 | | 292 | | function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual { 293 | | vm.assertNotEq(left, right); 294 | | } 295 | | 296 | | function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual { 297 | | vm.assertNotEq(left, right, err); 298 | | } 299 | | 300 | | function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual { 301 | | vm.assertNotEq(left, right); 302 | | } 303 | | 304 | | function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual { 305 | | vm.assertNotEq(left, right, err); 306 | | } 307 | | 308 | | function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual { 309 | | vm.assertNotEq(left, right); 310 | | } 311 | | 312 | | function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual { 313 | | vm.assertNotEq(left, right, err); 314 | | } 315 | | 316 | | function assertNotEq(address[] memory left, address[] memory right) internal pure virtual { 317 | | vm.assertNotEq(left, right); 318 | | } 319 | | 320 | | function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual { 321 | | vm.assertNotEq(left, right, err); 322 | | } 323 | | 324 | | function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual { 325 | | vm.assertNotEq(left, right); 326 | | } 327 | | 328 | | function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual { 329 | | vm.assertNotEq(left, right, err); 330 | | } 331 | | 332 | | function assertNotEq(string[] memory left, string[] memory right) internal pure virtual { 333 | | vm.assertNotEq(left, right); 334 | | } 335 | | 336 | | function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual { 337 | | vm.assertNotEq(left, right, err); 338 | | } 339 | | 340 | | function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual { 341 | | vm.assertNotEq(left, right); 342 | | } 343 | | 344 | | function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual { 345 | | vm.assertNotEq(left, right, err); 346 | | } 347 | | 348 | | function assertLt(uint256 left, uint256 right) internal pure virtual { 349 | | vm.assertLt(left, right); 350 | | } 351 | | 352 | | function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual { 353 | | vm.assertLt(left, right, err); 354 | | } 355 | | 356 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 357 | | vm.assertLtDecimal(left, right, decimals); 358 | | } 359 | | 360 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { 361 | | vm.assertLtDecimal(left, right, decimals, err); 362 | | } 363 | | 364 | | function assertLt(int256 left, int256 right) internal pure virtual { 365 | | vm.assertLt(left, right); 366 | | } 367 | | 368 | | function assertLt(int256 left, int256 right, string memory err) internal pure virtual { 369 | | vm.assertLt(left, right, err); 370 | | } 371 | | 372 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 373 | | vm.assertLtDecimal(left, right, decimals); 374 | | } 375 | | 376 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 377 | | vm.assertLtDecimal(left, right, decimals, err); 378 | | } 379 | | 380 | | function assertGt(uint256 left, uint256 right) internal pure virtual { 381 | | vm.assertGt(left, right); 382 | | } 383 | | 384 | | function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual { 385 | | vm.assertGt(left, right, err); 386 | | } 387 | | 388 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 389 | | vm.assertGtDecimal(left, right, decimals); 390 | | } 391 | | 392 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { 393 | | vm.assertGtDecimal(left, right, decimals, err); 394 | | } 395 | | 396 | | function assertGt(int256 left, int256 right) internal pure virtual { 397 | | vm.assertGt(left, right); 398 | | } 399 | | 400 | | function assertGt(int256 left, int256 right, string memory err) internal pure virtual { 401 | | vm.assertGt(left, right, err); 402 | | } 403 | | 404 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 405 | | vm.assertGtDecimal(left, right, decimals); 406 | | } 407 | | 408 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 409 | | vm.assertGtDecimal(left, right, decimals, err); 410 | | } 411 | | 412 | | function assertLe(uint256 left, uint256 right) internal pure virtual { 413 | | vm.assertLe(left, right); 414 | | } 415 | | 416 | | function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual { 417 | | vm.assertLe(left, right, err); 418 | | } 419 | | 420 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 421 | | vm.assertLeDecimal(left, right, decimals); 422 | | } 423 | | 424 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { 425 | | vm.assertLeDecimal(left, right, decimals, err); 426 | | } 427 | | 428 | | function assertLe(int256 left, int256 right) internal pure virtual { 429 | | vm.assertLe(left, right); 430 | | } 431 | | 432 | | function assertLe(int256 left, int256 right, string memory err) internal pure virtual { 433 | | vm.assertLe(left, right, err); 434 | | } 435 | | 436 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 437 | | vm.assertLeDecimal(left, right, decimals); 438 | | } 439 | | 440 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 441 | | vm.assertLeDecimal(left, right, decimals, err); 442 | | } 443 | | 444 | | function assertGe(uint256 left, uint256 right) internal pure virtual { 445 | | vm.assertGe(left, right); 446 | | } 447 | | 448 | | function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual { 449 | | vm.assertGe(left, right, err); 450 | | } 451 | | 452 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual { 453 | | vm.assertGeDecimal(left, right, decimals); 454 | | } 455 | | 456 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual { 457 | | vm.assertGeDecimal(left, right, decimals, err); 458 | | } 459 | | 460 | | function assertGe(int256 left, int256 right) internal pure virtual { 461 | | vm.assertGe(left, right); 462 | | } 463 | | 464 | | function assertGe(int256 left, int256 right, string memory err) internal pure virtual { 465 | | vm.assertGe(left, right, err); 466 | | } 467 | | 468 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual { 469 | | vm.assertGeDecimal(left, right, decimals); 470 | | } 471 | | 472 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual { 473 | | vm.assertGeDecimal(left, right, decimals, err); 474 | | } 475 | | 476 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual { 477 | | vm.assertApproxEqAbs(left, right, maxDelta); 478 | | } 479 | | 480 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err) 481 | | internal 482 | | pure 483 | | virtual 484 | | { 485 | | vm.assertApproxEqAbs(left, right, maxDelta, err); 486 | | } 487 | | 488 | | function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) 489 | | internal 490 | | pure 491 | | virtual 492 | | { 493 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); 494 | | } 495 | | 496 | | function assertApproxEqAbsDecimal( 497 | | uint256 left, 498 | | uint256 right, 499 | | uint256 maxDelta, 500 | | uint256 decimals, 501 | | string memory err 502 | | ) internal pure virtual { 503 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); 504 | | } 505 | | 506 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual { 507 | | vm.assertApproxEqAbs(left, right, maxDelta); 508 | | } 509 | | 510 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual { 511 | | vm.assertApproxEqAbs(left, right, maxDelta, err); 512 | | } 513 | | 514 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) 515 | | internal 516 | | pure 517 | | virtual 518 | | { 519 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals); 520 | | } 521 | | 522 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err) 523 | | internal 524 | | pure 525 | | virtual 526 | | { 527 | | vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err); 528 | | } 529 | | 530 | | function assertApproxEqRel( 531 | | uint256 left, 532 | | uint256 right, 533 | | uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% 534 | | ) internal pure virtual { 535 | | vm.assertApproxEqRel(left, right, maxPercentDelta); 536 | | } 537 | | 538 | | function assertApproxEqRel( 539 | | uint256 left, 540 | | uint256 right, 541 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 542 | | string memory err 543 | | ) internal pure virtual { 544 | | vm.assertApproxEqRel(left, right, maxPercentDelta, err); 545 | | } 546 | | 547 | | function assertApproxEqRelDecimal( 548 | | uint256 left, 549 | | uint256 right, 550 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 551 | | uint256 decimals 552 | | ) internal pure virtual { 553 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); 554 | | } 555 | | 556 | | function assertApproxEqRelDecimal( 557 | | uint256 left, 558 | | uint256 right, 559 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 560 | | uint256 decimals, 561 | | string memory err 562 | | ) internal pure virtual { 563 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); 564 | | } 565 | | 566 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual { 567 | | vm.assertApproxEqRel(left, right, maxPercentDelta); 568 | | } 569 | | 570 | | function assertApproxEqRel( 571 | | int256 left, 572 | | int256 right, 573 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 574 | | string memory err 575 | | ) internal pure virtual { 576 | | vm.assertApproxEqRel(left, right, maxPercentDelta, err); 577 | | } 578 | | 579 | | function assertApproxEqRelDecimal( 580 | | int256 left, 581 | | int256 right, 582 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 583 | | uint256 decimals 584 | | ) internal pure virtual { 585 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals); 586 | | } 587 | | 588 | | function assertApproxEqRelDecimal( 589 | | int256 left, 590 | | int256 right, 591 | | uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100% 592 | | uint256 decimals, 593 | | string memory err 594 | | ) internal pure virtual { 595 | | vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err); 596 | | } 597 | | 598 | | // Inherited from DSTest, not used but kept for backwards-compatibility 599 | | function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) { 600 | | return keccak256(left) == keccak256(right); 601 | | } 602 | | 603 | | function assertEq0(bytes memory left, bytes memory right) internal pure virtual { 604 | | assertEq(left, right); 605 | | } 606 | | 607 | | function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { 608 | | assertEq(left, right, err); 609 | | } 610 | | 611 | | function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual { 612 | | assertNotEq(left, right); 613 | | } 614 | | 615 | | function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual { 616 | | assertNotEq(left, right, err); 617 | | } 618 | | 619 | | function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual { 620 | | assertEqCall(target, callDataA, target, callDataB, true); 621 | | } 622 | | 623 | | function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB) 624 | | internal 625 | | virtual 626 | | { 627 | | assertEqCall(targetA, callDataA, targetB, callDataB, true); 628 | | } 629 | | 630 | | function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData) 631 | | internal 632 | | virtual 633 | | { 634 | | assertEqCall(target, callDataA, target, callDataB, strictRevertData); 635 | | } 636 | | 637 | | function assertEqCall( 638 | | address targetA, 639 | | bytes memory callDataA, 640 | | address targetB, 641 | | bytes memory callDataB, 642 | | bool strictRevertData 643 | | ) internal virtual { 644 | | (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA); 645 | | (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB); 646 | | 647 | | if (successA && successB) { 648 | | assertEq(returnDataA, returnDataB, "Call return data does not match"); 649 | | } 650 | | 651 | | if (!successA && !successB && strictRevertData) { 652 | | assertEq(returnDataA, returnDataB, "Call revert data does not match"); 653 | | } 654 | | 655 | | if (!successA && successB) { 656 | | emit log("Error: Calls were not equal"); 657 | | emit log_named_bytes(" Left call revert data", returnDataA); 658 | | emit log_named_bytes(" Right call return data", returnDataB); 659 | | revert("assertion failed"); 660 | | } 661 | | 662 | | if (successA && !successB) { 663 | | emit log("Error: Calls were not equal"); 664 | | emit log_named_bytes(" Left call return data", returnDataA); 665 | | emit log_named_bytes(" Right call revert data", returnDataB); 666 | | revert("assertion failed"); 667 | | } 668 | | } 669 | | } 670 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdChains.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | import {VmSafe} from "./Vm.sol"; 5 | | 6 | | /** 7 | | * StdChains provides information about EVM compatible chains that can be used in scripts/tests. 8 | | * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are 9 | | * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of 10 | | * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the 11 | | * alias used in this contract, which can be found as the first argument to the 12 | | * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. 13 | | * 14 | | * There are two main ways to use this contract: 15 | | * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or 16 | | * `setChain(string memory chainAlias, Chain memory chain)` 17 | | * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. 18 | | * 19 | | * The first time either of those are used, chains are initialized with the default set of RPC URLs. 20 | | * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in 21 | | * `defaultRpcUrls`. 22 | | * 23 | | * The `setChain` function is straightforward, and it simply saves off the given chain data. 24 | | * 25 | | * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say 26 | | * we want to retrieve the RPC URL for `mainnet`: 27 | | * - If you have specified data with `setChain`, it will return that. 28 | | * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it 29 | | * is valid (e.g. a URL is specified, or an environment variable is given and exists). 30 | | * - If neither of the above conditions is met, the default data is returned. 31 | | * 32 | | * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. 33 | | */ 34 | | abstract contract StdChains { 35 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 36 | | 37 | | bool private stdChainsInitialized; 38 | | 39 | | struct ChainData { 40 | | string name; 41 | | uint256 chainId; 42 | | string rpcUrl; 43 | | } 44 | | 45 | | struct Chain { 46 | | // The chain name. 47 | | string name; 48 | | // The chain's Chain ID. 49 | | uint256 chainId; 50 | | // The chain's alias. (i.e. what gets specified in `foundry.toml`). 51 | | string chainAlias; 52 | | // A default RPC endpoint for this chain. 53 | | // NOTE: This default RPC URL is included for convenience to facilitate quick tests and 54 | | // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy 55 | | // usage as you will be throttled and this is a disservice to others who need this endpoint. 56 | | string rpcUrl; 57 | | } 58 | | 59 | | // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. 60 | | mapping(string => Chain) private chains; 61 | | // Maps from the chain's alias to it's default RPC URL. 62 | | mapping(string => string) private defaultRpcUrls; 63 | | // Maps from a chain ID to it's alias. 64 | | mapping(uint256 => string) private idToAlias; 65 | | 66 | | bool private fallbackToDefaultRpcUrls = true; 67 | | 68 | | // The RPC URL will be fetched from config or defaultRpcUrls if possible. 69 | | function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { 70 | | require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); 71 | | 72 | | initializeStdChains(); 73 | | chain = chains[chainAlias]; 74 | | require( 75 | | chain.chainId != 0, 76 | | string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) 77 | | ); 78 | | 79 | | chain = getChainWithUpdatedRpcUrl(chainAlias, chain); 80 | | } 81 | | 82 | | function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { 83 | | require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); 84 | | initializeStdChains(); 85 | | string memory chainAlias = idToAlias[chainId]; 86 | | 87 | | chain = chains[chainAlias]; 88 | | 89 | | require( 90 | | chain.chainId != 0, 91 | | string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) 92 | | ); 93 | | 94 | | chain = getChainWithUpdatedRpcUrl(chainAlias, chain); 95 | | } 96 | | 97 | | // set chain info, with priority to argument's rpcUrl field. 98 | | function setChain(string memory chainAlias, ChainData memory chain) internal virtual { 99 | | require( 100 | | bytes(chainAlias).length != 0, 101 | | "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." 102 | | ); 103 | | 104 | | require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); 105 | | 106 | | initializeStdChains(); 107 | | string memory foundAlias = idToAlias[chain.chainId]; 108 | | 109 | | require( 110 | | bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), 111 | | string( 112 | | abi.encodePacked( 113 | | "StdChains setChain(string,ChainData): Chain ID ", 114 | | vm.toString(chain.chainId), 115 | | " already used by \"", 116 | | foundAlias, 117 | | "\"." 118 | | ) 119 | | ) 120 | | ); 121 | | 122 | | uint256 oldChainId = chains[chainAlias].chainId; 123 | | delete idToAlias[oldChainId]; 124 | | 125 | | chains[chainAlias] = 126 | | Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); 127 | | idToAlias[chain.chainId] = chainAlias; 128 | | } 129 | | 130 | | // set chain info, with priority to argument's rpcUrl field. 131 | | function setChain(string memory chainAlias, Chain memory chain) internal virtual { 132 | | setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); 133 | | } 134 | | 135 | | function _toUpper(string memory str) private pure returns (string memory) { 136 | | bytes memory strb = bytes(str); 137 | | bytes memory copy = new bytes(strb.length); 138 | | for (uint256 i = 0; i < strb.length; i++) { 139 | | bytes1 b = strb[i]; 140 | | if (b >= 0x61 && b <= 0x7A) { 141 | | copy[i] = bytes1(uint8(b) - 32); 142 | | } else { 143 | | copy[i] = b; 144 | | } 145 | | } 146 | | return string(copy); 147 | | } 148 | | 149 | | // lookup rpcUrl, in descending order of priority: 150 | | // current -> config (foundry.toml) -> environment variable -> default 151 | | function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) 152 | | private 153 | | view 154 | | returns (Chain memory) 155 | | { 156 | | if (bytes(chain.rpcUrl).length == 0) { 157 | | try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { 158 | | chain.rpcUrl = configRpcUrl; 159 | | } catch (bytes memory err) { 160 | | string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); 161 | | if (fallbackToDefaultRpcUrls) { 162 | | chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); 163 | | } else { 164 | | chain.rpcUrl = vm.envString(envName); 165 | | } 166 | | // Distinguish 'not found' from 'cannot read' 167 | | // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions 168 | | bytes memory oldNotFoundError = 169 | | abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); 170 | | bytes memory newNotFoundError = abi.encodeWithSignature( 171 | | "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) 172 | | ); 173 | | bytes32 errHash = keccak256(err); 174 | | if ( 175 | | (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) 176 | | || bytes(chain.rpcUrl).length == 0 177 | | ) { 178 | | /// @solidity memory-safe-assembly 179 | | assembly { 180 | | revert(add(32, err), mload(err)) 181 | | } 182 | | } 183 | | } 184 | | } 185 | | return chain; 186 | | } 187 | | 188 | | function setFallbackToDefaultRpcUrls(bool useDefault) internal { 189 | | fallbackToDefaultRpcUrls = useDefault; 190 | | } 191 | | 192 | | function initializeStdChains() private { 193 | | if (stdChainsInitialized) return; 194 | | 195 | | stdChainsInitialized = true; 196 | | 197 | | // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol` 198 | | setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); 199 | | setChainWithDefaultRpcUrl( 200 | | "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP") 201 | | ); 202 | | setChainWithDefaultRpcUrl( 203 | | "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") 204 | | ); 205 | | setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io")); 206 | | setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); 207 | | setChainWithDefaultRpcUrl( 208 | | "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io") 209 | | ); 210 | | setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); 211 | | setChainWithDefaultRpcUrl( 212 | | "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc") 213 | | ); 214 | | setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); 215 | | setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); 216 | | setChainWithDefaultRpcUrl( 217 | | "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology") 218 | | ); 219 | | setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); 220 | | setChainWithDefaultRpcUrl( 221 | | "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") 222 | | ); 223 | | setChainWithDefaultRpcUrl( 224 | | "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") 225 | | ); 226 | | setChainWithDefaultRpcUrl( 227 | | "bnb_smart_chain_testnet", 228 | | ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") 229 | | ); 230 | | setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); 231 | | setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); 232 | | setChainWithDefaultRpcUrl( 233 | | "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") 234 | | ); 235 | | setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); 236 | | setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org")); 237 | | setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); 238 | | setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io")); 239 | | setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io")); 240 | | setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/")); 241 | | setChainWithDefaultRpcUrl( 242 | | "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/") 243 | | ); 244 | | setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com")); 245 | | setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com")); 246 | | setChainWithDefaultRpcUrl( 247 | | "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com") 248 | | ); 249 | | setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc")); 250 | | setChainWithDefaultRpcUrl( 251 | | "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc") 252 | | ); 253 | | } 254 | | 255 | | // set chain info, with priority to chainAlias' rpc url in foundry.toml 256 | | function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { 257 | | string memory rpcUrl = chain.rpcUrl; 258 | | defaultRpcUrls[chainAlias] = rpcUrl; 259 | | chain.rpcUrl = ""; 260 | | setChain(chainAlias, chain); 261 | | chain.rpcUrl = rpcUrl; // restore argument 262 | | } 263 | | } 264 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdCheats.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | import {StdStorage, stdStorage} from "./StdStorage.sol"; 7 | | import {console2} from "./console2.sol"; 8 | | import {Vm} from "./Vm.sol"; 9 | | 10 | | abstract contract StdCheatsSafe { 11 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); 12 | | 13 | | uint256 private constant UINT256_MAX = 14 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 15 | | 16 | | bool private gasMeteringOff; 17 | | 18 | | // Data structures to parse Transaction objects from the broadcast artifact 19 | | // that conform to EIP1559. The Raw structs is what is parsed from the JSON 20 | | // and then converted to the one that is used by the user for better UX. 21 | | 22 | | struct RawTx1559 { 23 | | string[] arguments; 24 | | address contractAddress; 25 | | string contractName; 26 | | // json value name = function 27 | | string functionSig; 28 | | bytes32 hash; 29 | | // json value name = tx 30 | | RawTx1559Detail txDetail; 31 | | // json value name = type 32 | | string opcode; 33 | | } 34 | | 35 | | struct RawTx1559Detail { 36 | | AccessList[] accessList; 37 | | bytes data; 38 | | address from; 39 | | bytes gas; 40 | | bytes nonce; 41 | | address to; 42 | | bytes txType; 43 | | bytes value; 44 | | } 45 | | 46 | | struct Tx1559 { 47 | | string[] arguments; 48 | | address contractAddress; 49 | | string contractName; 50 | | string functionSig; 51 | | bytes32 hash; 52 | | Tx1559Detail txDetail; 53 | | string opcode; 54 | | } 55 | | 56 | | struct Tx1559Detail { 57 | | AccessList[] accessList; 58 | | bytes data; 59 | | address from; 60 | | uint256 gas; 61 | | uint256 nonce; 62 | | address to; 63 | | uint256 txType; 64 | | uint256 value; 65 | | } 66 | | 67 | | // Data structures to parse Transaction objects from the broadcast artifact 68 | | // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON 69 | | // and then converted to the one that is used by the user for better UX. 70 | | 71 | | struct TxLegacy { 72 | | string[] arguments; 73 | | address contractAddress; 74 | | string contractName; 75 | | string functionSig; 76 | | string hash; 77 | | string opcode; 78 | | TxDetailLegacy transaction; 79 | | } 80 | | 81 | | struct TxDetailLegacy { 82 | | AccessList[] accessList; 83 | | uint256 chainId; 84 | | bytes data; 85 | | address from; 86 | | uint256 gas; 87 | | uint256 gasPrice; 88 | | bytes32 hash; 89 | | uint256 nonce; 90 | | bytes1 opcode; 91 | | bytes32 r; 92 | | bytes32 s; 93 | | uint256 txType; 94 | | address to; 95 | | uint8 v; 96 | | uint256 value; 97 | | } 98 | | 99 | | struct AccessList { 100 | | address accessAddress; 101 | | bytes32[] storageKeys; 102 | | } 103 | | 104 | | // Data structures to parse Receipt objects from the broadcast artifact. 105 | | // The Raw structs is what is parsed from the JSON 106 | | // and then converted to the one that is used by the user for better UX. 107 | | 108 | | struct RawReceipt { 109 | | bytes32 blockHash; 110 | | bytes blockNumber; 111 | | address contractAddress; 112 | | bytes cumulativeGasUsed; 113 | | bytes effectiveGasPrice; 114 | | address from; 115 | | bytes gasUsed; 116 | | RawReceiptLog[] logs; 117 | | bytes logsBloom; 118 | | bytes status; 119 | | address to; 120 | | bytes32 transactionHash; 121 | | bytes transactionIndex; 122 | | } 123 | | 124 | | struct Receipt { 125 | | bytes32 blockHash; 126 | | uint256 blockNumber; 127 | | address contractAddress; 128 | | uint256 cumulativeGasUsed; 129 | | uint256 effectiveGasPrice; 130 | | address from; 131 | | uint256 gasUsed; 132 | | ReceiptLog[] logs; 133 | | bytes logsBloom; 134 | | uint256 status; 135 | | address to; 136 | | bytes32 transactionHash; 137 | | uint256 transactionIndex; 138 | | } 139 | | 140 | | // Data structures to parse the entire broadcast artifact, assuming the 141 | | // transactions conform to EIP1559. 142 | | 143 | | struct EIP1559ScriptArtifact { 144 | | string[] libraries; 145 | | string path; 146 | | string[] pending; 147 | | Receipt[] receipts; 148 | | uint256 timestamp; 149 | | Tx1559[] transactions; 150 | | TxReturn[] txReturns; 151 | | } 152 | | 153 | | struct RawEIP1559ScriptArtifact { 154 | | string[] libraries; 155 | | string path; 156 | | string[] pending; 157 | | RawReceipt[] receipts; 158 | | TxReturn[] txReturns; 159 | | uint256 timestamp; 160 | | RawTx1559[] transactions; 161 | | } 162 | | 163 | | struct RawReceiptLog { 164 | | // json value = address 165 | | address logAddress; 166 | | bytes32 blockHash; 167 | | bytes blockNumber; 168 | | bytes data; 169 | | bytes logIndex; 170 | | bool removed; 171 | | bytes32[] topics; 172 | | bytes32 transactionHash; 173 | | bytes transactionIndex; 174 | | bytes transactionLogIndex; 175 | | } 176 | | 177 | | struct ReceiptLog { 178 | | // json value = address 179 | | address logAddress; 180 | | bytes32 blockHash; 181 | | uint256 blockNumber; 182 | | bytes data; 183 | | uint256 logIndex; 184 | | bytes32[] topics; 185 | | uint256 transactionIndex; 186 | | uint256 transactionLogIndex; 187 | | bool removed; 188 | | } 189 | | 190 | | struct TxReturn { 191 | | string internalType; 192 | | string value; 193 | | } 194 | | 195 | | struct Account { 196 | | address addr; 197 | | uint256 key; 198 | | } 199 | | 200 | | enum AddressType { 201 | | Payable, 202 | | NonPayable, 203 | | ZeroAddress, 204 | | Precompile, 205 | | ForgeAddress 206 | | } 207 | | 208 | | // Checks that `addr` is not blacklisted by token contracts that have a blacklist. 209 | | function assumeNotBlacklisted(address token, address addr) internal view virtual { 210 | | // Nothing to check if `token` is not a contract. 211 | | uint256 tokenCodeSize; 212 | | assembly { 213 | | tokenCodeSize := extcodesize(token) 214 | | } 215 | | require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract."); 216 | | 217 | | bool success; 218 | | bytes memory returnData; 219 | | 220 | | // 4-byte selector for `isBlacklisted(address)`, used by USDC. 221 | | (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr)); 222 | | vm.assume(!success || abi.decode(returnData, (bool)) == false); 223 | | 224 | | // 4-byte selector for `isBlackListed(address)`, used by USDT. 225 | | (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr)); 226 | | vm.assume(!success || abi.decode(returnData, (bool)) == false); 227 | | } 228 | | 229 | | // Checks that `addr` is not blacklisted by token contracts that have a blacklist. 230 | | // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for 231 | | // backwards compatibility, since this name was used in the original PR which already has 232 | | // a release. This function can be removed in a future release once we want a breaking change. 233 | | function assumeNoBlacklisted(address token, address addr) internal view virtual { 234 | | assumeNotBlacklisted(token, addr); 235 | | } 236 | | 237 | | function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { 238 | | if (addressType == AddressType.Payable) { 239 | | assumeNotPayable(addr); 240 | | } else if (addressType == AddressType.NonPayable) { 241 | | assumePayable(addr); 242 | | } else if (addressType == AddressType.ZeroAddress) { 243 | | assumeNotZeroAddress(addr); 244 | | } else if (addressType == AddressType.Precompile) { 245 | | assumeNotPrecompile(addr); 246 | | } else if (addressType == AddressType.ForgeAddress) { 247 | | assumeNotForgeAddress(addr); 248 | | } 249 | | } 250 | | 251 | | function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { 252 | | assumeAddressIsNot(addr, addressType1); 253 | | assumeAddressIsNot(addr, addressType2); 254 | | } 255 | | 256 | | function assumeAddressIsNot( 257 | | address addr, 258 | | AddressType addressType1, 259 | | AddressType addressType2, 260 | | AddressType addressType3 261 | | ) internal virtual { 262 | | assumeAddressIsNot(addr, addressType1); 263 | | assumeAddressIsNot(addr, addressType2); 264 | | assumeAddressIsNot(addr, addressType3); 265 | | } 266 | | 267 | | function assumeAddressIsNot( 268 | | address addr, 269 | | AddressType addressType1, 270 | | AddressType addressType2, 271 | | AddressType addressType3, 272 | | AddressType addressType4 273 | | ) internal virtual { 274 | | assumeAddressIsNot(addr, addressType1); 275 | | assumeAddressIsNot(addr, addressType2); 276 | | assumeAddressIsNot(addr, addressType3); 277 | | assumeAddressIsNot(addr, addressType4); 278 | | } 279 | | 280 | | // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to 281 | | // `addr` and checking the `success` return value. 282 | | // NOTE: This function may result in state changes depending on the fallback/receive logic 283 | | // implemented by `addr`, which should be taken into account when this function is used. 284 | | function _isPayable(address addr) private returns (bool) { 285 | | require( 286 | | addr.balance < UINT256_MAX, 287 | | "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds" 288 | | ); 289 | | uint256 origBalanceTest = address(this).balance; 290 | | uint256 origBalanceAddr = address(addr).balance; 291 | | 292 | | vm.deal(address(this), 1); 293 | | (bool success,) = payable(addr).call{value: 1}(""); 294 | | 295 | | // reset balances 296 | | vm.deal(address(this), origBalanceTest); 297 | | vm.deal(addr, origBalanceAddr); 298 | | 299 | | return success; 300 | | } 301 | | 302 | | // NOTE: This function may result in state changes depending on the fallback/receive logic 303 | | // implemented by `addr`, which should be taken into account when this function is used. See the 304 | | // `_isPayable` method for more information. 305 | | function assumePayable(address addr) internal virtual { 306 | | vm.assume(_isPayable(addr)); 307 | | } 308 | | 309 | | function assumeNotPayable(address addr) internal virtual { 310 | | vm.assume(!_isPayable(addr)); 311 | | } 312 | | 313 | | function assumeNotZeroAddress(address addr) internal pure virtual { 314 | | vm.assume(addr != address(0)); 315 | | } 316 | | 317 | | function assumeNotPrecompile(address addr) internal pure virtual { 318 | | assumeNotPrecompile(addr, _pureChainId()); 319 | | } 320 | | 321 | | function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { 322 | | // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific 323 | | // address), but the same rationale for excluding them applies so we include those too. 324 | | 325 | | // These are reserved by Ethereum and may be on all EVM-compatible chains. 326 | | vm.assume(addr < address(0x1) || addr > address(0xff)); 327 | | 328 | | // forgefmt: disable-start 329 | | if (chainId == 10 || chainId == 420) { 330 | | // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21 331 | | vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800)); 332 | | } else if (chainId == 42161 || chainId == 421613) { 333 | | // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains 334 | | vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068)); 335 | | } else if (chainId == 43114 || chainId == 43113) { 336 | | // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59 337 | | vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff)); 338 | | vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF)); 339 | | vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff)); 340 | | } 341 | | // forgefmt: disable-end 342 | | } 343 | | 344 | | function assumeNotForgeAddress(address addr) internal pure virtual { 345 | | // vm, console, and Create2Deployer addresses 346 | | vm.assume( 347 | | addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67 348 | | && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C 349 | | ); 350 | | } 351 | | 352 | | function readEIP1559ScriptArtifact(string memory path) 353 | | internal 354 | | view 355 | | virtual 356 | | returns (EIP1559ScriptArtifact memory) 357 | | { 358 | | string memory data = vm.readFile(path); 359 | | bytes memory parsedData = vm.parseJson(data); 360 | | RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact)); 361 | | EIP1559ScriptArtifact memory artifact; 362 | | artifact.libraries = rawArtifact.libraries; 363 | | artifact.path = rawArtifact.path; 364 | | artifact.timestamp = rawArtifact.timestamp; 365 | | artifact.pending = rawArtifact.pending; 366 | | artifact.txReturns = rawArtifact.txReturns; 367 | | artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts); 368 | | artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions); 369 | | return artifact; 370 | | } 371 | | 372 | | function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { 373 | | Tx1559[] memory txs = new Tx1559[](rawTxs.length); 374 | | for (uint256 i; i < rawTxs.length; i++) { 375 | | txs[i] = rawToConvertedEIPTx1559(rawTxs[i]); 376 | | } 377 | | return txs; 378 | | } 379 | | 380 | | function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { 381 | | Tx1559 memory transaction; 382 | | transaction.arguments = rawTx.arguments; 383 | | transaction.contractName = rawTx.contractName; 384 | | transaction.functionSig = rawTx.functionSig; 385 | | transaction.hash = rawTx.hash; 386 | | transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail); 387 | | transaction.opcode = rawTx.opcode; 388 | | return transaction; 389 | | } 390 | | 391 | | function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) 392 | | internal 393 | | pure 394 | | virtual 395 | | returns (Tx1559Detail memory) 396 | | { 397 | | Tx1559Detail memory txDetail; 398 | | txDetail.data = rawDetail.data; 399 | | txDetail.from = rawDetail.from; 400 | | txDetail.to = rawDetail.to; 401 | | txDetail.nonce = _bytesToUint(rawDetail.nonce); 402 | | txDetail.txType = _bytesToUint(rawDetail.txType); 403 | | txDetail.value = _bytesToUint(rawDetail.value); 404 | | txDetail.gas = _bytesToUint(rawDetail.gas); 405 | | txDetail.accessList = rawDetail.accessList; 406 | | return txDetail; 407 | | } 408 | | 409 | | function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { 410 | | string memory deployData = vm.readFile(path); 411 | | bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); 412 | | RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[])); 413 | | return rawToConvertedEIPTx1559s(rawTxs); 414 | | } 415 | | 416 | | function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { 417 | | string memory deployData = vm.readFile(path); 418 | | string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); 419 | | bytes memory parsedDeployData = vm.parseJson(deployData, key); 420 | | RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559)); 421 | | return rawToConvertedEIPTx1559(rawTx); 422 | | } 423 | | 424 | | // Analogous to readTransactions, but for receipts. 425 | | function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { 426 | | string memory deployData = vm.readFile(path); 427 | | bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); 428 | | RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[])); 429 | | return rawToConvertedReceipts(rawReceipts); 430 | | } 431 | | 432 | | function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { 433 | | string memory deployData = vm.readFile(path); 434 | | string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); 435 | | bytes memory parsedDeployData = vm.parseJson(deployData, key); 436 | | RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt)); 437 | | return rawToConvertedReceipt(rawReceipt); 438 | | } 439 | | 440 | | function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { 441 | | Receipt[] memory receipts = new Receipt[](rawReceipts.length); 442 | | for (uint256 i; i < rawReceipts.length; i++) { 443 | | receipts[i] = rawToConvertedReceipt(rawReceipts[i]); 444 | | } 445 | | return receipts; 446 | | } 447 | | 448 | | function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { 449 | | Receipt memory receipt; 450 | | receipt.blockHash = rawReceipt.blockHash; 451 | | receipt.to = rawReceipt.to; 452 | | receipt.from = rawReceipt.from; 453 | | receipt.contractAddress = rawReceipt.contractAddress; 454 | | receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice); 455 | | receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed); 456 | | receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed); 457 | | receipt.status = _bytesToUint(rawReceipt.status); 458 | | receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex); 459 | | receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber); 460 | | receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs); 461 | | receipt.logsBloom = rawReceipt.logsBloom; 462 | | receipt.transactionHash = rawReceipt.transactionHash; 463 | | return receipt; 464 | | } 465 | | 466 | | function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) 467 | | internal 468 | | pure 469 | | virtual 470 | | returns (ReceiptLog[] memory) 471 | | { 472 | | ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length); 473 | | for (uint256 i; i < rawLogs.length; i++) { 474 | | logs[i].logAddress = rawLogs[i].logAddress; 475 | | logs[i].blockHash = rawLogs[i].blockHash; 476 | | logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber); 477 | | logs[i].data = rawLogs[i].data; 478 | | logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex); 479 | | logs[i].topics = rawLogs[i].topics; 480 | | logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex); 481 | | logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex); 482 | | logs[i].removed = rawLogs[i].removed; 483 | | } 484 | | return logs; 485 | | } 486 | | 487 | | // Deploy a contract by fetching the contract bytecode from 488 | | // the artifacts directory 489 | | // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` 490 | | function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { 491 | | bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); 492 | | /// @solidity memory-safe-assembly 493 | | assembly { 494 | | addr := create(0, add(bytecode, 0x20), mload(bytecode)) 495 | | } 496 | | 497 | | require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); 498 | | } 499 | | 500 | | function deployCode(string memory what) internal virtual returns (address addr) { 501 | | bytes memory bytecode = vm.getCode(what); 502 | | /// @solidity memory-safe-assembly 503 | | assembly { 504 | | addr := create(0, add(bytecode, 0x20), mload(bytecode)) 505 | | } 506 | | 507 | | require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); 508 | | } 509 | | 510 | | /// @dev deploy contract with value on construction 511 | | function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { 512 | | bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); 513 | | /// @solidity memory-safe-assembly 514 | | assembly { 515 | | addr := create(val, add(bytecode, 0x20), mload(bytecode)) 516 | | } 517 | | 518 | | require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); 519 | | } 520 | | 521 | | function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { 522 | | bytes memory bytecode = vm.getCode(what); 523 | | /// @solidity memory-safe-assembly 524 | | assembly { 525 | | addr := create(val, add(bytecode, 0x20), mload(bytecode)) 526 | | } 527 | | 528 | | require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); 529 | | } 530 | | 531 | | // creates a labeled address and the corresponding private key 532 | | function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { 533 | | privateKey = uint256(keccak256(abi.encodePacked(name))); 534 | | addr = vm.addr(privateKey); 535 | | vm.label(addr, name); 536 | | } 537 | | 538 | | // creates a labeled address 539 | | function makeAddr(string memory name) internal virtual returns (address addr) { 540 | | (addr,) = makeAddrAndKey(name); 541 | | } 542 | | 543 | | // Destroys an account immediately, sending the balance to beneficiary. 544 | | // Destroying means: balance will be zero, code will be empty, and nonce will be 0 545 | | // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce 546 | | // only after tx ends, this will run immediately. 547 | | function destroyAccount(address who, address beneficiary) internal virtual { 548 | | uint256 currBalance = who.balance; 549 | | vm.etch(who, abi.encode()); 550 | | vm.deal(who, 0); 551 | | vm.resetNonce(who); 552 | | 553 | | uint256 beneficiaryBalance = beneficiary.balance; 554 | | vm.deal(beneficiary, currBalance + beneficiaryBalance); 555 | | } 556 | | 557 | | // creates a struct containing both a labeled address and the corresponding private key 558 | | function makeAccount(string memory name) internal virtual returns (Account memory account) { 559 | | (account.addr, account.key) = makeAddrAndKey(name); 560 | | } 561 | | 562 | | function deriveRememberKey(string memory mnemonic, uint32 index) 563 | | internal 564 | | virtual 565 | | returns (address who, uint256 privateKey) 566 | | { 567 | | privateKey = vm.deriveKey(mnemonic, index); 568 | | who = vm.rememberKey(privateKey); 569 | | } 570 | | 571 | | function _bytesToUint(bytes memory b) private pure returns (uint256) { 572 | | require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32."); 573 | | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); 574 | | } 575 | | 576 | | function isFork() internal view virtual returns (bool status) { 577 | | try vm.activeFork() { 578 | | status = true; 579 | | } catch (bytes memory) {} 580 | | } 581 | | 582 | | modifier skipWhenForking() { 583 | | if (!isFork()) { 584 | | _; 585 | | } 586 | | } 587 | | 588 | | modifier skipWhenNotForking() { 589 | | if (isFork()) { 590 | | _; 591 | | } 592 | | } 593 | | 594 | | modifier noGasMetering() { 595 | | vm.pauseGasMetering(); 596 | | // To prevent turning gas monitoring back on with nested functions that use this modifier, 597 | | // we check if gasMetering started in the off position. If it did, we don't want to turn 598 | | // it back on until we exit the top level function that used the modifier 599 | | // 600 | | // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well. 601 | | // funcA will have `gasStartedOff` as false, funcB will have it as true, 602 | | // so we only turn metering back on at the end of the funcA 603 | | bool gasStartedOff = gasMeteringOff; 604 | | gasMeteringOff = true; 605 | | 606 | | _; 607 | | 608 | | // if gas metering was on when this modifier was called, turn it back on at the end 609 | | if (!gasStartedOff) { 610 | | gasMeteringOff = false; 611 | | vm.resumeGasMetering(); 612 | | } 613 | | } 614 | | 615 | | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no 616 | | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We 617 | | // can't simply access the chain ID in a normal view or pure function because the solc View Pure 618 | | // Checker changed `chainid` from pure to view in 0.8.0. 619 | | function _viewChainId() private view returns (uint256 chainId) { 620 | | // Assembly required since `block.chainid` was introduced in 0.8.0. 621 | | assembly { 622 | | chainId := chainid() 623 | | } 624 | | 625 | | address(this); // Silence warnings in older Solc versions. 626 | | } 627 | | 628 | | function _pureChainId() private pure returns (uint256 chainId) { 629 | | function() internal view returns (uint256) fnIn = _viewChainId; 630 | | function() internal pure returns (uint256) pureChainId; 631 | | assembly { 632 | | pureChainId := fnIn 633 | | } 634 | | chainId = pureChainId(); 635 | | } 636 | | } 637 | | 638 | | // Wrappers around cheatcodes to avoid footguns 639 | | abstract contract StdCheats is StdCheatsSafe { 640 | | using stdStorage for StdStorage; 641 | | 642 | | StdStorage private stdstore; 643 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); 644 | | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; 645 | | 646 | | // Skip forward or rewind time by the specified number of seconds 647 | | function skip(uint256 time) internal virtual { 648 | | vm.warp(block.timestamp + time); 649 | | } 650 | | 651 | | function rewind(uint256 time) internal virtual { 652 | | vm.warp(block.timestamp - time); 653 | | } 654 | | 655 | | // Setup a prank from an address that has some ether 656 | | function hoax(address msgSender) internal virtual { 657 | | vm.deal(msgSender, 1 << 128); 658 | | vm.prank(msgSender); 659 | | } 660 | | 661 | | function hoax(address msgSender, uint256 give) internal virtual { 662 | | vm.deal(msgSender, give); 663 | | vm.prank(msgSender); 664 | | } 665 | | 666 | | function hoax(address msgSender, address origin) internal virtual { 667 | | vm.deal(msgSender, 1 << 128); 668 | | vm.prank(msgSender, origin); 669 | | } 670 | | 671 | | function hoax(address msgSender, address origin, uint256 give) internal virtual { 672 | | vm.deal(msgSender, give); 673 | | vm.prank(msgSender, origin); 674 | | } 675 | | 676 | | // Start perpetual prank from an address that has some ether 677 | | function startHoax(address msgSender) internal virtual { 678 | | vm.deal(msgSender, 1 << 128); 679 | | vm.startPrank(msgSender); 680 | | } 681 | | 682 | | function startHoax(address msgSender, uint256 give) internal virtual { 683 | | vm.deal(msgSender, give); 684 | | vm.startPrank(msgSender); 685 | | } 686 | | 687 | | // Start perpetual prank from an address that has some ether 688 | | // tx.origin is set to the origin parameter 689 | | function startHoax(address msgSender, address origin) internal virtual { 690 | | vm.deal(msgSender, 1 << 128); 691 | | vm.startPrank(msgSender, origin); 692 | | } 693 | | 694 | | function startHoax(address msgSender, address origin, uint256 give) internal virtual { 695 | | vm.deal(msgSender, give); 696 | | vm.startPrank(msgSender, origin); 697 | | } 698 | | 699 | | function changePrank(address msgSender) internal virtual { 700 | | console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); 701 | | vm.stopPrank(); 702 | | vm.startPrank(msgSender); 703 | | } 704 | | 705 | | function changePrank(address msgSender, address txOrigin) internal virtual { 706 | | vm.stopPrank(); 707 | | vm.startPrank(msgSender, txOrigin); 708 | | } 709 | | 710 | | // The same as Vm's `deal` 711 | | // Use the alternative signature for ERC20 tokens 712 | | function deal(address to, uint256 give) internal virtual { 713 | | vm.deal(to, give); 714 | | } 715 | | 716 | | // Set the balance of an account for any ERC20 token 717 | | // Use the alternative signature to update `totalSupply` 718 | | function deal(address token, address to, uint256 give) internal virtual { 719 | | deal(token, to, give, false); 720 | | } 721 | | 722 | | // Set the balance of an account for any ERC1155 token 723 | | // Use the alternative signature to update `totalSupply` 724 | | function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { 725 | | dealERC1155(token, to, id, give, false); 726 | | } 727 | | 728 | | function deal(address token, address to, uint256 give, bool adjust) internal virtual { 729 | | // get current balance 730 | | (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); 731 | | uint256 prevBal = abi.decode(balData, (uint256)); 732 | | 733 | | // update balance 734 | | stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give); 735 | | 736 | | // update total supply 737 | | if (adjust) { 738 | | (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd)); 739 | | uint256 totSup = abi.decode(totSupData, (uint256)); 740 | | if (give < prevBal) { 741 | | totSup -= (prevBal - give); 742 | | } else { 743 | | totSup += (give - prevBal); 744 | | } 745 | | stdstore.target(token).sig(0x18160ddd).checked_write(totSup); 746 | | } 747 | | } 748 | | 749 | | function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { 750 | | // get current balance 751 | | (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); 752 | | uint256 prevBal = abi.decode(balData, (uint256)); 753 | | 754 | | // update balance 755 | | stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give); 756 | | 757 | | // update total supply 758 | | if (adjust) { 759 | | (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id)); 760 | | require( 761 | | totSupData.length != 0, 762 | | "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply." 763 | | ); 764 | | uint256 totSup = abi.decode(totSupData, (uint256)); 765 | | if (give < prevBal) { 766 | | totSup -= (prevBal - give); 767 | | } else { 768 | | totSup += (give - prevBal); 769 | | } 770 | | stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup); 771 | | } 772 | | } 773 | | 774 | | function dealERC721(address token, address to, uint256 id) internal virtual { 775 | | // check if token id is already minted and the actual owner. 776 | | (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); 777 | | require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted."); 778 | | 779 | | // get owner current balance 780 | | (, bytes memory fromBalData) = 781 | | token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address)))); 782 | | uint256 fromPrevBal = abi.decode(fromBalData, (uint256)); 783 | | 784 | | // get new user current balance 785 | | (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); 786 | | uint256 toPrevBal = abi.decode(toBalData, (uint256)); 787 | | 788 | | // update balances 789 | | stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal); 790 | | stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal); 791 | | 792 | | // update owner 793 | | stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); 794 | | } 795 | | 796 | | function deployCodeTo(string memory what, address where) internal virtual { 797 | | deployCodeTo(what, "", 0, where); 798 | | } 799 | | 800 | | function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { 801 | | deployCodeTo(what, args, 0, where); 802 | | } 803 | | 804 | | function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { 805 | | bytes memory creationCode = vm.getCode(what); 806 | | vm.etch(where, abi.encodePacked(creationCode, args)); 807 | | (bool success, bytes memory runtimeBytecode) = where.call{value: value}(""); 808 | | require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode."); 809 | | vm.etch(where, runtimeBytecode); 810 | | } 811 | | 812 | | // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere. 813 | | function console2_log_StdCheats(string memory p0) private view { 814 | | (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0)); 815 | | status; 816 | | } 817 | | } 818 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdError.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test 3 | | pragma solidity >=0.6.2 <0.9.0; 4 | | 5 | | library stdError { 6 | | bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); 7 | | bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); 8 | | bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); 9 | | bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); 10 | | bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); 11 | | bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); 12 | | bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); 13 | | bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); 14 | | bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); 15 | | } 16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdInvariant.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | abstract contract StdInvariant { 7 | | struct FuzzSelector { 8 | | address addr; 9 | | bytes4[] selectors; 10 | | } 11 | | 12 | | struct FuzzArtifactSelector { 13 | | string artifact; 14 | | bytes4[] selectors; 15 | | } 16 | | 17 | | struct FuzzInterface { 18 | | address addr; 19 | | string[] artifacts; 20 | | } 21 | | 22 | | address[] private _excludedContracts; 23 | | address[] private _excludedSenders; 24 | | address[] private _targetedContracts; 25 | | address[] private _targetedSenders; 26 | | 27 | | string[] private _excludedArtifacts; 28 | | string[] private _targetedArtifacts; 29 | | 30 | | FuzzArtifactSelector[] private _targetedArtifactSelectors; 31 | | 32 | | FuzzSelector[] private _excludedSelectors; 33 | | FuzzSelector[] private _targetedSelectors; 34 | | 35 | | FuzzInterface[] private _targetedInterfaces; 36 | | 37 | | // Functions for users: 38 | | // These are intended to be called in tests. 39 | | 40 | | function excludeContract(address newExcludedContract_) internal { 41 | | _excludedContracts.push(newExcludedContract_); 42 | | } 43 | | 44 | | function excludeSelector(FuzzSelector memory newExcludedSelector_) internal { 45 | | _excludedSelectors.push(newExcludedSelector_); 46 | | } 47 | | 48 | | function excludeSender(address newExcludedSender_) internal { 49 | | _excludedSenders.push(newExcludedSender_); 50 | | } 51 | | 52 | | function excludeArtifact(string memory newExcludedArtifact_) internal { 53 | | _excludedArtifacts.push(newExcludedArtifact_); 54 | | } 55 | | 56 | | function targetArtifact(string memory newTargetedArtifact_) internal { 57 | | _targetedArtifacts.push(newTargetedArtifact_); 58 | | } 59 | | 60 | | function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal { 61 | | _targetedArtifactSelectors.push(newTargetedArtifactSelector_); 62 | | } 63 | | 64 | | function targetContract(address newTargetedContract_) internal { 65 | | _targetedContracts.push(newTargetedContract_); 66 | | } 67 | | 68 | | function targetSelector(FuzzSelector memory newTargetedSelector_) internal { 69 | | _targetedSelectors.push(newTargetedSelector_); 70 | | } 71 | | 72 | | function targetSender(address newTargetedSender_) internal { 73 | | _targetedSenders.push(newTargetedSender_); 74 | | } 75 | | 76 | | function targetInterface(FuzzInterface memory newTargetedInterface_) internal { 77 | | _targetedInterfaces.push(newTargetedInterface_); 78 | | } 79 | | 80 | | // Functions for forge: 81 | | // These are called by forge to run invariant tests and don't need to be called in tests. 82 | | 83 | * | function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { 84 | * | excludedArtifacts_ = _excludedArtifacts; 85 | | } 86 | | 87 | * | function excludeContracts() public view returns (address[] memory excludedContracts_) { 88 | * | excludedContracts_ = _excludedContracts; 89 | | } 90 | | 91 | * | function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) { 92 | * | excludedSelectors_ = _excludedSelectors; 93 | | } 94 | | 95 | * | function excludeSenders() public view returns (address[] memory excludedSenders_) { 96 | * | excludedSenders_ = _excludedSenders; 97 | | } 98 | | 99 | * | function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { 100 | * | targetedArtifacts_ = _targetedArtifacts; 101 | | } 102 | | 103 | * | function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) { 104 | * | targetedArtifactSelectors_ = _targetedArtifactSelectors; 105 | | } 106 | | 107 | * | function targetContracts() public view returns (address[] memory targetedContracts_) { 108 | * | targetedContracts_ = _targetedContracts; 109 | | } 110 | | 111 | * | function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { 112 | * | targetedSelectors_ = _targetedSelectors; 113 | | } 114 | | 115 | * | function targetSenders() public view returns (address[] memory targetedSenders_) { 116 | * | targetedSenders_ = _targetedSenders; 117 | | } 118 | | 119 | * | function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { 120 | * | targetedInterfaces_ = _targetedInterfaces; 121 | | } 122 | | } 123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdJson.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.0 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | import {VmSafe} from "./Vm.sol"; 7 | | 8 | | // Helpers for parsing and writing JSON files 9 | | // To parse: 10 | | // ``` 11 | | // using stdJson for string; 12 | | // string memory json = vm.readFile("<some_path>"); 13 | | // json.readUint("<json_path>"); 14 | | // ``` 15 | | // To write: 16 | | // ``` 17 | | // using stdJson for string; 18 | | // string memory json = "json"; 19 | | // json.serialize("a", uint256(123)); 20 | | // string memory semiFinal = json.serialize("b", string("test")); 21 | | // string memory finalJson = json.serialize("c", semiFinal); 22 | | // finalJson.write("<some_path>"); 23 | | // ``` 24 | | 25 | * | library stdJson { 26 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 27 | | 28 | | function keyExists(string memory json, string memory key) internal view returns (bool) { 29 | | return vm.keyExistsJson(json, key); 30 | | } 31 | | 32 | | function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { 33 | | return vm.parseJson(json, key); 34 | | } 35 | | 36 | | function readUint(string memory json, string memory key) internal pure returns (uint256) { 37 | | return vm.parseJsonUint(json, key); 38 | | } 39 | | 40 | | function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { 41 | | return vm.parseJsonUintArray(json, key); 42 | | } 43 | | 44 | | function readInt(string memory json, string memory key) internal pure returns (int256) { 45 | | return vm.parseJsonInt(json, key); 46 | | } 47 | | 48 | | function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { 49 | | return vm.parseJsonIntArray(json, key); 50 | | } 51 | | 52 | | function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { 53 | | return vm.parseJsonBytes32(json, key); 54 | | } 55 | | 56 | | function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { 57 | | return vm.parseJsonBytes32Array(json, key); 58 | | } 59 | | 60 | | function readString(string memory json, string memory key) internal pure returns (string memory) { 61 | | return vm.parseJsonString(json, key); 62 | | } 63 | | 64 | | function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { 65 | | return vm.parseJsonStringArray(json, key); 66 | | } 67 | | 68 | | function readAddress(string memory json, string memory key) internal pure returns (address) { 69 | | return vm.parseJsonAddress(json, key); 70 | | } 71 | | 72 | | function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { 73 | | return vm.parseJsonAddressArray(json, key); 74 | | } 75 | | 76 | | function readBool(string memory json, string memory key) internal pure returns (bool) { 77 | | return vm.parseJsonBool(json, key); 78 | | } 79 | | 80 | | function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { 81 | | return vm.parseJsonBoolArray(json, key); 82 | | } 83 | | 84 | | function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { 85 | | return vm.parseJsonBytes(json, key); 86 | | } 87 | | 88 | | function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { 89 | | return vm.parseJsonBytesArray(json, key); 90 | | } 91 | | 92 | | function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { 93 | | return keyExists(json, key) ? readUint(json, key) : defaultValue; 94 | | } 95 | | 96 | | function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) 97 | | internal 98 | | view 99 | | returns (uint256[] memory) 100 | | { 101 | | return keyExists(json, key) ? readUintArray(json, key) : defaultValue; 102 | | } 103 | | 104 | | function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { 105 | | return keyExists(json, key) ? readInt(json, key) : defaultValue; 106 | | } 107 | | 108 | | function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) 109 | | internal 110 | | view 111 | | returns (int256[] memory) 112 | | { 113 | | return keyExists(json, key) ? readIntArray(json, key) : defaultValue; 114 | | } 115 | | 116 | | function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) 117 | | internal 118 | | view 119 | | returns (bytes32) 120 | | { 121 | | return keyExists(json, key) ? readBytes32(json, key) : defaultValue; 122 | | } 123 | | 124 | | function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) 125 | | internal 126 | | view 127 | | returns (bytes32[] memory) 128 | | { 129 | | return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; 130 | | } 131 | | 132 | | function readStringOr(string memory json, string memory key, string memory defaultValue) 133 | | internal 134 | | view 135 | | returns (string memory) 136 | | { 137 | | return keyExists(json, key) ? readString(json, key) : defaultValue; 138 | | } 139 | | 140 | | function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) 141 | | internal 142 | | view 143 | | returns (string[] memory) 144 | | { 145 | | return keyExists(json, key) ? readStringArray(json, key) : defaultValue; 146 | | } 147 | | 148 | | function readAddressOr(string memory json, string memory key, address defaultValue) 149 | | internal 150 | | view 151 | | returns (address) 152 | | { 153 | | return keyExists(json, key) ? readAddress(json, key) : defaultValue; 154 | | } 155 | | 156 | | function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) 157 | | internal 158 | | view 159 | | returns (address[] memory) 160 | | { 161 | | return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; 162 | | } 163 | | 164 | | function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { 165 | | return keyExists(json, key) ? readBool(json, key) : defaultValue; 166 | | } 167 | | 168 | | function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) 169 | | internal 170 | | view 171 | | returns (bool[] memory) 172 | | { 173 | | return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; 174 | | } 175 | | 176 | | function readBytesOr(string memory json, string memory key, bytes memory defaultValue) 177 | | internal 178 | | view 179 | | returns (bytes memory) 180 | | { 181 | | return keyExists(json, key) ? readBytes(json, key) : defaultValue; 182 | | } 183 | | 184 | | function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) 185 | | internal 186 | | view 187 | | returns (bytes[] memory) 188 | | { 189 | | return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; 190 | | } 191 | | 192 | | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { 193 | | return vm.serializeJson(jsonKey, rootObject); 194 | | } 195 | | 196 | | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { 197 | | return vm.serializeBool(jsonKey, key, value); 198 | | } 199 | | 200 | | function serialize(string memory jsonKey, string memory key, bool[] memory value) 201 | | internal 202 | | returns (string memory) 203 | | { 204 | | return vm.serializeBool(jsonKey, key, value); 205 | | } 206 | | 207 | | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { 208 | | return vm.serializeUint(jsonKey, key, value); 209 | | } 210 | | 211 | | function serialize(string memory jsonKey, string memory key, uint256[] memory value) 212 | | internal 213 | | returns (string memory) 214 | | { 215 | | return vm.serializeUint(jsonKey, key, value); 216 | | } 217 | | 218 | | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { 219 | | return vm.serializeInt(jsonKey, key, value); 220 | | } 221 | | 222 | | function serialize(string memory jsonKey, string memory key, int256[] memory value) 223 | | internal 224 | | returns (string memory) 225 | | { 226 | | return vm.serializeInt(jsonKey, key, value); 227 | | } 228 | | 229 | | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { 230 | | return vm.serializeAddress(jsonKey, key, value); 231 | | } 232 | | 233 | | function serialize(string memory jsonKey, string memory key, address[] memory value) 234 | | internal 235 | | returns (string memory) 236 | | { 237 | | return vm.serializeAddress(jsonKey, key, value); 238 | | } 239 | | 240 | | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { 241 | | return vm.serializeBytes32(jsonKey, key, value); 242 | | } 243 | | 244 | | function serialize(string memory jsonKey, string memory key, bytes32[] memory value) 245 | | internal 246 | | returns (string memory) 247 | | { 248 | | return vm.serializeBytes32(jsonKey, key, value); 249 | | } 250 | | 251 | | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { 252 | | return vm.serializeBytes(jsonKey, key, value); 253 | | } 254 | | 255 | | function serialize(string memory jsonKey, string memory key, bytes[] memory value) 256 | | internal 257 | | returns (string memory) 258 | | { 259 | | return vm.serializeBytes(jsonKey, key, value); 260 | | } 261 | | 262 | | function serialize(string memory jsonKey, string memory key, string memory value) 263 | | internal 264 | | returns (string memory) 265 | | { 266 | | return vm.serializeString(jsonKey, key, value); 267 | | } 268 | | 269 | | function serialize(string memory jsonKey, string memory key, string[] memory value) 270 | | internal 271 | | returns (string memory) 272 | | { 273 | | return vm.serializeString(jsonKey, key, value); 274 | | } 275 | | 276 | | function write(string memory jsonKey, string memory path) internal { 277 | | vm.writeJson(jsonKey, path); 278 | | } 279 | | 280 | | function write(string memory jsonKey, string memory path, string memory valueKey) internal { 281 | | vm.writeJson(jsonKey, path, valueKey); 282 | | } 283 | | } 284 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdMath.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | * | library stdMath { 5 | | int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; 6 | | 7 | | function abs(int256 a) internal pure returns (uint256) { 8 | | // Required or it will fail when `a = type(int256).min` 9 | | if (a == INT256_MIN) { 10 | | return 57896044618658097711785492504343953926634992332820282019728792003956564819968; 11 | | } 12 | | 13 | | return uint256(a > 0 ? a : -a); 14 | | } 15 | | 16 | | function delta(uint256 a, uint256 b) internal pure returns (uint256) { 17 | | return a > b ? a - b : b - a; 18 | | } 19 | | 20 | | function delta(int256 a, int256 b) internal pure returns (uint256) { 21 | | // a and b are of the same sign 22 | | // this works thanks to two's complement, the left-most bit is the sign bit 23 | | if ((a ^ b) > -1) { 24 | | return delta(abs(a), abs(b)); 25 | | } 26 | | 27 | | // a and b are of opposite signs 28 | | return abs(a) + abs(b); 29 | | } 30 | | 31 | | function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { 32 | | uint256 absDelta = delta(a, b); 33 | | 34 | | return absDelta * 1e18 / b; 35 | | } 36 | | 37 | | function percentDelta(int256 a, int256 b) internal pure returns (uint256) { 38 | | uint256 absDelta = delta(a, b); 39 | | uint256 absB = abs(b); 40 | | 41 | | return absDelta * 1e18 / absB; 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdStorage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | import {Vm} from "./Vm.sol"; 5 | | 6 | | struct FindData { 7 | | uint256 slot; 8 | | uint256 offsetLeft; 9 | | uint256 offsetRight; 10 | | bool found; 11 | | } 12 | | 13 | | struct StdStorage { 14 | | mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds; 15 | | bytes32[] _keys; 16 | | bytes4 _sig; 17 | | uint256 _depth; 18 | | address _target; 19 | | bytes32 _set; 20 | | bool _enable_packed_slots; 21 | | bytes _calldata; 22 | | } 23 | | 24 | * | library stdStorageSafe { 25 | | event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot); 26 | | event WARNING_UninitedSlot(address who, uint256 slot); 27 | | 28 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); 29 | | uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; 30 | | 31 | | function sigs(string memory sigStr) internal pure returns (bytes4) { 32 | | return bytes4(keccak256(bytes(sigStr))); 33 | | } 34 | | 35 | | function getCallParams(StdStorage storage self) internal view returns (bytes memory) { 36 | | if (self._calldata.length == 0) { 37 | | return flatten(self._keys); 38 | | } else { 39 | | return self._calldata; 40 | | } 41 | | } 42 | | 43 | | // Calls target contract with configured parameters 44 | | function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { 45 | | bytes memory cald = abi.encodePacked(self._sig, getCallParams(self)); 46 | | (bool success, bytes memory rdat) = self._target.staticcall(cald); 47 | | bytes32 result = bytesToBytes32(rdat, 32 * self._depth); 48 | | 49 | | return (success, result); 50 | | } 51 | | 52 | | // Tries mutating slot value to determine if the targeted value is stored in it. 53 | | // If current value is 0, then we are setting slot value to type(uint256).max 54 | | // Otherwise, we set it to 0. That way, return value should always be affected. 55 | | function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { 56 | | bytes32 prevSlotValue = vm.load(self._target, slot); 57 | | (bool success, bytes32 prevReturnValue) = callTarget(self); 58 | | 59 | | bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0); 60 | | vm.store(self._target, slot, testVal); 61 | | 62 | | (, bytes32 newReturnValue) = callTarget(self); 63 | | 64 | | vm.store(self._target, slot, prevSlotValue); 65 | | 66 | | return (success && (prevReturnValue != newReturnValue)); 67 | | } 68 | | 69 | | // Tries setting one of the bits in slot to 1 until return value changes. 70 | | // Index of resulted bit is an offset packed slot has from left/right side 71 | | function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { 72 | | for (uint256 offset = 0; offset < 256; offset++) { 73 | | uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); 74 | | vm.store(self._target, slot, bytes32(valueToPut)); 75 | | 76 | | (bool success, bytes32 data) = callTarget(self); 77 | | 78 | | if (success && (uint256(data) > 0)) { 79 | | return (true, offset); 80 | | } 81 | | } 82 | | return (false, 0); 83 | | } 84 | | 85 | | function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { 86 | | bytes32 prevSlotValue = vm.load(self._target, slot); 87 | | 88 | | (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true); 89 | | (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false); 90 | | 91 | | // `findOffset` may mutate slot value, so we are setting it to initial value 92 | | vm.store(self._target, slot, prevSlotValue); 93 | | return (foundLeft && foundRight, offsetLeft, offsetRight); 94 | | } 95 | | 96 | | function find(StdStorage storage self) internal returns (FindData storage) { 97 | | return find(self, true); 98 | | } 99 | | 100 | | /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against 101 | | // slot complexity: 102 | | // if flat, will be bytes32(uint256(uint)); 103 | | // if map, will be keccak256(abi.encode(key, uint(slot))); 104 | | // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot))))); 105 | | // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth); 106 | | function find(StdStorage storage self, bool _clear) internal returns (FindData storage) { 107 | | address who = self._target; 108 | | bytes4 fsig = self._sig; 109 | | uint256 field_depth = self._depth; 110 | | bytes memory params = getCallParams(self); 111 | | 112 | | // calldata to test against 113 | | if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { 114 | | if (_clear) { 115 | | clear(self); 116 | | } 117 | | return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; 118 | | } 119 | | vm.record(); 120 | | (, bytes32 callResult) = callTarget(self); 121 | | (bytes32[] memory reads,) = vm.accesses(address(who)); 122 | | 123 | | if (reads.length == 0) { 124 | | revert("stdStorage find(StdStorage): No storage use detected for target."); 125 | | } else { 126 | | for (uint256 i = reads.length; --i >= 0;) { 127 | | bytes32 prev = vm.load(who, reads[i]); 128 | | if (prev == bytes32(0)) { 129 | | emit WARNING_UninitedSlot(who, uint256(reads[i])); 130 | | } 131 | | 132 | | if (!checkSlotMutatesCall(self, reads[i])) { 133 | | continue; 134 | | } 135 | | 136 | | (uint256 offsetLeft, uint256 offsetRight) = (0, 0); 137 | | 138 | | if (self._enable_packed_slots) { 139 | | bool found; 140 | | (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]); 141 | | if (!found) { 142 | | continue; 143 | | } 144 | | } 145 | | 146 | | // Check that value between found offsets is equal to the current call result 147 | | uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight; 148 | | 149 | | if (uint256(callResult) != curVal) { 150 | | continue; 151 | | } 152 | | 153 | | emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i])); 154 | | self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] = 155 | | FindData(uint256(reads[i]), offsetLeft, offsetRight, true); 156 | | break; 157 | | } 158 | | } 159 | | 160 | | require( 161 | | self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found, 162 | | "stdStorage find(StdStorage): Slot(s) not found." 163 | | ); 164 | | 165 | | if (_clear) { 166 | | clear(self); 167 | | } 168 | | return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; 169 | | } 170 | | 171 | | function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { 172 | | self._target = _target; 173 | | return self; 174 | | } 175 | | 176 | | function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { 177 | | self._sig = _sig; 178 | | return self; 179 | | } 180 | | 181 | | function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { 182 | | self._sig = sigs(_sig); 183 | | return self; 184 | | } 185 | | 186 | | function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { 187 | | self._calldata = _calldata; 188 | | return self; 189 | | } 190 | | 191 | | function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { 192 | | self._keys.push(bytes32(uint256(uint160(who)))); 193 | | return self; 194 | | } 195 | | 196 | | function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { 197 | | self._keys.push(bytes32(amt)); 198 | | return self; 199 | | } 200 | | 201 | | function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { 202 | | self._keys.push(key); 203 | | return self; 204 | | } 205 | | 206 | | function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { 207 | | self._enable_packed_slots = true; 208 | | return self; 209 | | } 210 | | 211 | | function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { 212 | | self._depth = _depth; 213 | | return self; 214 | | } 215 | | 216 | | function read(StdStorage storage self) private returns (bytes memory) { 217 | | FindData storage data = find(self, false); 218 | | uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight); 219 | | uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight; 220 | | clear(self); 221 | | return abi.encode(value); 222 | | } 223 | | 224 | | function read_bytes32(StdStorage storage self) internal returns (bytes32) { 225 | | return abi.decode(read(self), (bytes32)); 226 | | } 227 | | 228 | | function read_bool(StdStorage storage self) internal returns (bool) { 229 | | int256 v = read_int(self); 230 | | if (v == 0) return false; 231 | | if (v == 1) return true; 232 | | revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); 233 | | } 234 | | 235 | | function read_address(StdStorage storage self) internal returns (address) { 236 | | return abi.decode(read(self), (address)); 237 | | } 238 | | 239 | | function read_uint(StdStorage storage self) internal returns (uint256) { 240 | | return abi.decode(read(self), (uint256)); 241 | | } 242 | | 243 | | function read_int(StdStorage storage self) internal returns (int256) { 244 | | return abi.decode(read(self), (int256)); 245 | | } 246 | | 247 | | function parent(StdStorage storage self) internal returns (uint256, bytes32) { 248 | | address who = self._target; 249 | | uint256 field_depth = self._depth; 250 | | vm.startMappingRecording(); 251 | | uint256 child = find(self, true).slot - field_depth; 252 | | (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); 253 | | if (!found) { 254 | | revert( 255 | | "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." 256 | | ); 257 | | } 258 | | return (uint256(parent_slot), key); 259 | | } 260 | | 261 | | function root(StdStorage storage self) internal returns (uint256) { 262 | | address who = self._target; 263 | | uint256 field_depth = self._depth; 264 | | vm.startMappingRecording(); 265 | | uint256 child = find(self, true).slot - field_depth; 266 | | bool found; 267 | | bytes32 root_slot; 268 | | bytes32 parent_slot; 269 | | (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child)); 270 | | if (!found) { 271 | | revert( 272 | | "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called." 273 | | ); 274 | | } 275 | | while (found) { 276 | | root_slot = parent_slot; 277 | | (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot)); 278 | | } 279 | | return uint256(root_slot); 280 | | } 281 | | 282 | | function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) { 283 | | bytes32 out; 284 | | 285 | | uint256 max = b.length > 32 ? 32 : b.length; 286 | | for (uint256 i = 0; i < max; i++) { 287 | | out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); 288 | | } 289 | | return out; 290 | | } 291 | | 292 | | function flatten(bytes32[] memory b) private pure returns (bytes memory) { 293 | | bytes memory result = new bytes(b.length * 32); 294 | | for (uint256 i = 0; i < b.length; i++) { 295 | | bytes32 k = b[i]; 296 | | /// @solidity memory-safe-assembly 297 | | assembly { 298 | | mstore(add(result, add(32, mul(32, i))), k) 299 | | } 300 | | } 301 | | 302 | | return result; 303 | | } 304 | | 305 | | function clear(StdStorage storage self) internal { 306 | | delete self._target; 307 | | delete self._sig; 308 | | delete self._keys; 309 | | delete self._depth; 310 | | delete self._enable_packed_slots; 311 | | delete self._calldata; 312 | | } 313 | | 314 | | // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` 315 | | // (slotValue & mask) >> offsetRight will be the value of the given packed variable 316 | | function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { 317 | | // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; 318 | | // using assembly because (1 << 256) causes overflow 319 | | assembly { 320 | | mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1)) 321 | | } 322 | | } 323 | | 324 | | // Returns slot value with updated packed variable. 325 | | function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) 326 | | internal 327 | | pure 328 | | returns (bytes32 newValue) 329 | | { 330 | | return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight)); 331 | | } 332 | | } 333 | | 334 | * | library stdStorage { 335 | | Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); 336 | | 337 | | function sigs(string memory sigStr) internal pure returns (bytes4) { 338 | | return stdStorageSafe.sigs(sigStr); 339 | | } 340 | | 341 | | function find(StdStorage storage self) internal returns (uint256) { 342 | | return find(self, true); 343 | | } 344 | | 345 | | function find(StdStorage storage self, bool _clear) internal returns (uint256) { 346 | | return stdStorageSafe.find(self, _clear).slot; 347 | | } 348 | | 349 | | function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { 350 | | return stdStorageSafe.target(self, _target); 351 | | } 352 | | 353 | | function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { 354 | | return stdStorageSafe.sig(self, _sig); 355 | | } 356 | | 357 | | function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { 358 | | return stdStorageSafe.sig(self, _sig); 359 | | } 360 | | 361 | | function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { 362 | | return stdStorageSafe.with_key(self, who); 363 | | } 364 | | 365 | | function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { 366 | | return stdStorageSafe.with_key(self, amt); 367 | | } 368 | | 369 | | function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { 370 | | return stdStorageSafe.with_key(self, key); 371 | | } 372 | | 373 | | function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { 374 | | return stdStorageSafe.with_calldata(self, _calldata); 375 | | } 376 | | 377 | | function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { 378 | | return stdStorageSafe.enable_packed_slots(self); 379 | | } 380 | | 381 | | function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { 382 | | return stdStorageSafe.depth(self, _depth); 383 | | } 384 | | 385 | | function clear(StdStorage storage self) internal { 386 | | stdStorageSafe.clear(self); 387 | | } 388 | | 389 | | function checked_write(StdStorage storage self, address who) internal { 390 | | checked_write(self, bytes32(uint256(uint160(who)))); 391 | | } 392 | | 393 | | function checked_write(StdStorage storage self, uint256 amt) internal { 394 | | checked_write(self, bytes32(amt)); 395 | | } 396 | | 397 | | function checked_write_int(StdStorage storage self, int256 val) internal { 398 | | checked_write(self, bytes32(uint256(val))); 399 | | } 400 | | 401 | | function checked_write(StdStorage storage self, bool write) internal { 402 | | bytes32 t; 403 | | /// @solidity memory-safe-assembly 404 | | assembly { 405 | | t := write 406 | | } 407 | | checked_write(self, t); 408 | | } 409 | | 410 | | function checked_write(StdStorage storage self, bytes32 set) internal { 411 | | address who = self._target; 412 | | bytes4 fsig = self._sig; 413 | | uint256 field_depth = self._depth; 414 | | bytes memory params = stdStorageSafe.getCallParams(self); 415 | | 416 | | if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) { 417 | | find(self, false); 418 | | } 419 | | FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; 420 | | if ((data.offsetLeft + data.offsetRight) > 0) { 421 | | uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight)); 422 | | require( 423 | | uint256(set) < maxVal, 424 | | string( 425 | | abi.encodePacked( 426 | | "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ", 427 | | vm.toString(maxVal) 428 | | ) 429 | | ) 430 | | ); 431 | | } 432 | | bytes32 curVal = vm.load(who, bytes32(data.slot)); 433 | | bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight); 434 | | 435 | | vm.store(who, bytes32(data.slot), valToSet); 436 | | 437 | | (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self); 438 | | 439 | | if (!success || callResult != set) { 440 | | vm.store(who, bytes32(data.slot), curVal); 441 | | revert("stdStorage find(StdStorage): Failed to write value."); 442 | | } 443 | | clear(self); 444 | | } 445 | | 446 | | function read_bytes32(StdStorage storage self) internal returns (bytes32) { 447 | | return stdStorageSafe.read_bytes32(self); 448 | | } 449 | | 450 | | function read_bool(StdStorage storage self) internal returns (bool) { 451 | | return stdStorageSafe.read_bool(self); 452 | | } 453 | | 454 | | function read_address(StdStorage storage self) internal returns (address) { 455 | | return stdStorageSafe.read_address(self); 456 | | } 457 | | 458 | | function read_uint(StdStorage storage self) internal returns (uint256) { 459 | | return stdStorageSafe.read_uint(self); 460 | | } 461 | | 462 | | function read_int(StdStorage storage self) internal returns (int256) { 463 | | return stdStorageSafe.read_int(self); 464 | | } 465 | | 466 | | function parent(StdStorage storage self) internal returns (uint256, bytes32) { 467 | | return stdStorageSafe.parent(self); 468 | | } 469 | | 470 | | function root(StdStorage storage self) internal returns (uint256) { 471 | | return stdStorageSafe.root(self); 472 | | } 473 | | } 474 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdStyle.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.4.22 <0.9.0; 3 | | 4 | | import {VmSafe} from "./Vm.sol"; 5 | | 6 | * | library StdStyle { 7 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 8 | | 9 | | string constant RED = "\u001b[91m"; 10 | | string constant GREEN = "\u001b[92m"; 11 | | string constant YELLOW = "\u001b[93m"; 12 | | string constant BLUE = "\u001b[94m"; 13 | | string constant MAGENTA = "\u001b[95m"; 14 | | string constant CYAN = "\u001b[96m"; 15 | | string constant BOLD = "\u001b[1m"; 16 | | string constant DIM = "\u001b[2m"; 17 | | string constant ITALIC = "\u001b[3m"; 18 | | string constant UNDERLINE = "\u001b[4m"; 19 | | string constant INVERSE = "\u001b[7m"; 20 | | string constant RESET = "\u001b[0m"; 21 | | 22 | | function styleConcat(string memory style, string memory self) private pure returns (string memory) { 23 | | return string(abi.encodePacked(style, self, RESET)); 24 | | } 25 | | 26 | | function red(string memory self) internal pure returns (string memory) { 27 | | return styleConcat(RED, self); 28 | | } 29 | | 30 | | function red(uint256 self) internal pure returns (string memory) { 31 | | return red(vm.toString(self)); 32 | | } 33 | | 34 | | function red(int256 self) internal pure returns (string memory) { 35 | | return red(vm.toString(self)); 36 | | } 37 | | 38 | | function red(address self) internal pure returns (string memory) { 39 | | return red(vm.toString(self)); 40 | | } 41 | | 42 | | function red(bool self) internal pure returns (string memory) { 43 | | return red(vm.toString(self)); 44 | | } 45 | | 46 | | function redBytes(bytes memory self) internal pure returns (string memory) { 47 | | return red(vm.toString(self)); 48 | | } 49 | | 50 | | function redBytes32(bytes32 self) internal pure returns (string memory) { 51 | | return red(vm.toString(self)); 52 | | } 53 | | 54 | | function green(string memory self) internal pure returns (string memory) { 55 | | return styleConcat(GREEN, self); 56 | | } 57 | | 58 | | function green(uint256 self) internal pure returns (string memory) { 59 | | return green(vm.toString(self)); 60 | | } 61 | | 62 | | function green(int256 self) internal pure returns (string memory) { 63 | | return green(vm.toString(self)); 64 | | } 65 | | 66 | | function green(address self) internal pure returns (string memory) { 67 | | return green(vm.toString(self)); 68 | | } 69 | | 70 | | function green(bool self) internal pure returns (string memory) { 71 | | return green(vm.toString(self)); 72 | | } 73 | | 74 | | function greenBytes(bytes memory self) internal pure returns (string memory) { 75 | | return green(vm.toString(self)); 76 | | } 77 | | 78 | | function greenBytes32(bytes32 self) internal pure returns (string memory) { 79 | | return green(vm.toString(self)); 80 | | } 81 | | 82 | | function yellow(string memory self) internal pure returns (string memory) { 83 | | return styleConcat(YELLOW, self); 84 | | } 85 | | 86 | | function yellow(uint256 self) internal pure returns (string memory) { 87 | | return yellow(vm.toString(self)); 88 | | } 89 | | 90 | | function yellow(int256 self) internal pure returns (string memory) { 91 | | return yellow(vm.toString(self)); 92 | | } 93 | | 94 | | function yellow(address self) internal pure returns (string memory) { 95 | | return yellow(vm.toString(self)); 96 | | } 97 | | 98 | | function yellow(bool self) internal pure returns (string memory) { 99 | | return yellow(vm.toString(self)); 100 | | } 101 | | 102 | | function yellowBytes(bytes memory self) internal pure returns (string memory) { 103 | | return yellow(vm.toString(self)); 104 | | } 105 | | 106 | | function yellowBytes32(bytes32 self) internal pure returns (string memory) { 107 | | return yellow(vm.toString(self)); 108 | | } 109 | | 110 | | function blue(string memory self) internal pure returns (string memory) { 111 | | return styleConcat(BLUE, self); 112 | | } 113 | | 114 | | function blue(uint256 self) internal pure returns (string memory) { 115 | | return blue(vm.toString(self)); 116 | | } 117 | | 118 | | function blue(int256 self) internal pure returns (string memory) { 119 | | return blue(vm.toString(self)); 120 | | } 121 | | 122 | | function blue(address self) internal pure returns (string memory) { 123 | | return blue(vm.toString(self)); 124 | | } 125 | | 126 | | function blue(bool self) internal pure returns (string memory) { 127 | | return blue(vm.toString(self)); 128 | | } 129 | | 130 | | function blueBytes(bytes memory self) internal pure returns (string memory) { 131 | | return blue(vm.toString(self)); 132 | | } 133 | | 134 | | function blueBytes32(bytes32 self) internal pure returns (string memory) { 135 | | return blue(vm.toString(self)); 136 | | } 137 | | 138 | | function magenta(string memory self) internal pure returns (string memory) { 139 | | return styleConcat(MAGENTA, self); 140 | | } 141 | | 142 | | function magenta(uint256 self) internal pure returns (string memory) { 143 | | return magenta(vm.toString(self)); 144 | | } 145 | | 146 | | function magenta(int256 self) internal pure returns (string memory) { 147 | | return magenta(vm.toString(self)); 148 | | } 149 | | 150 | | function magenta(address self) internal pure returns (string memory) { 151 | | return magenta(vm.toString(self)); 152 | | } 153 | | 154 | | function magenta(bool self) internal pure returns (string memory) { 155 | | return magenta(vm.toString(self)); 156 | | } 157 | | 158 | | function magentaBytes(bytes memory self) internal pure returns (string memory) { 159 | | return magenta(vm.toString(self)); 160 | | } 161 | | 162 | | function magentaBytes32(bytes32 self) internal pure returns (string memory) { 163 | | return magenta(vm.toString(self)); 164 | | } 165 | | 166 | | function cyan(string memory self) internal pure returns (string memory) { 167 | | return styleConcat(CYAN, self); 168 | | } 169 | | 170 | | function cyan(uint256 self) internal pure returns (string memory) { 171 | | return cyan(vm.toString(self)); 172 | | } 173 | | 174 | | function cyan(int256 self) internal pure returns (string memory) { 175 | | return cyan(vm.toString(self)); 176 | | } 177 | | 178 | | function cyan(address self) internal pure returns (string memory) { 179 | | return cyan(vm.toString(self)); 180 | | } 181 | | 182 | | function cyan(bool self) internal pure returns (string memory) { 183 | | return cyan(vm.toString(self)); 184 | | } 185 | | 186 | | function cyanBytes(bytes memory self) internal pure returns (string memory) { 187 | | return cyan(vm.toString(self)); 188 | | } 189 | | 190 | | function cyanBytes32(bytes32 self) internal pure returns (string memory) { 191 | | return cyan(vm.toString(self)); 192 | | } 193 | | 194 | | function bold(string memory self) internal pure returns (string memory) { 195 | | return styleConcat(BOLD, self); 196 | | } 197 | | 198 | | function bold(uint256 self) internal pure returns (string memory) { 199 | | return bold(vm.toString(self)); 200 | | } 201 | | 202 | | function bold(int256 self) internal pure returns (string memory) { 203 | | return bold(vm.toString(self)); 204 | | } 205 | | 206 | | function bold(address self) internal pure returns (string memory) { 207 | | return bold(vm.toString(self)); 208 | | } 209 | | 210 | | function bold(bool self) internal pure returns (string memory) { 211 | | return bold(vm.toString(self)); 212 | | } 213 | | 214 | | function boldBytes(bytes memory self) internal pure returns (string memory) { 215 | | return bold(vm.toString(self)); 216 | | } 217 | | 218 | | function boldBytes32(bytes32 self) internal pure returns (string memory) { 219 | | return bold(vm.toString(self)); 220 | | } 221 | | 222 | | function dim(string memory self) internal pure returns (string memory) { 223 | | return styleConcat(DIM, self); 224 | | } 225 | | 226 | | function dim(uint256 self) internal pure returns (string memory) { 227 | | return dim(vm.toString(self)); 228 | | } 229 | | 230 | | function dim(int256 self) internal pure returns (string memory) { 231 | | return dim(vm.toString(self)); 232 | | } 233 | | 234 | | function dim(address self) internal pure returns (string memory) { 235 | | return dim(vm.toString(self)); 236 | | } 237 | | 238 | | function dim(bool self) internal pure returns (string memory) { 239 | | return dim(vm.toString(self)); 240 | | } 241 | | 242 | | function dimBytes(bytes memory self) internal pure returns (string memory) { 243 | | return dim(vm.toString(self)); 244 | | } 245 | | 246 | | function dimBytes32(bytes32 self) internal pure returns (string memory) { 247 | | return dim(vm.toString(self)); 248 | | } 249 | | 250 | | function italic(string memory self) internal pure returns (string memory) { 251 | | return styleConcat(ITALIC, self); 252 | | } 253 | | 254 | | function italic(uint256 self) internal pure returns (string memory) { 255 | | return italic(vm.toString(self)); 256 | | } 257 | | 258 | | function italic(int256 self) internal pure returns (string memory) { 259 | | return italic(vm.toString(self)); 260 | | } 261 | | 262 | | function italic(address self) internal pure returns (string memory) { 263 | | return italic(vm.toString(self)); 264 | | } 265 | | 266 | | function italic(bool self) internal pure returns (string memory) { 267 | | return italic(vm.toString(self)); 268 | | } 269 | | 270 | | function italicBytes(bytes memory self) internal pure returns (string memory) { 271 | | return italic(vm.toString(self)); 272 | | } 273 | | 274 | | function italicBytes32(bytes32 self) internal pure returns (string memory) { 275 | | return italic(vm.toString(self)); 276 | | } 277 | | 278 | | function underline(string memory self) internal pure returns (string memory) { 279 | | return styleConcat(UNDERLINE, self); 280 | | } 281 | | 282 | | function underline(uint256 self) internal pure returns (string memory) { 283 | | return underline(vm.toString(self)); 284 | | } 285 | | 286 | | function underline(int256 self) internal pure returns (string memory) { 287 | | return underline(vm.toString(self)); 288 | | } 289 | | 290 | | function underline(address self) internal pure returns (string memory) { 291 | | return underline(vm.toString(self)); 292 | | } 293 | | 294 | | function underline(bool self) internal pure returns (string memory) { 295 | | return underline(vm.toString(self)); 296 | | } 297 | | 298 | | function underlineBytes(bytes memory self) internal pure returns (string memory) { 299 | | return underline(vm.toString(self)); 300 | | } 301 | | 302 | | function underlineBytes32(bytes32 self) internal pure returns (string memory) { 303 | | return underline(vm.toString(self)); 304 | | } 305 | | 306 | | function inverse(string memory self) internal pure returns (string memory) { 307 | | return styleConcat(INVERSE, self); 308 | | } 309 | | 310 | | function inverse(uint256 self) internal pure returns (string memory) { 311 | | return inverse(vm.toString(self)); 312 | | } 313 | | 314 | | function inverse(int256 self) internal pure returns (string memory) { 315 | | return inverse(vm.toString(self)); 316 | | } 317 | | 318 | | function inverse(address self) internal pure returns (string memory) { 319 | | return inverse(vm.toString(self)); 320 | | } 321 | | 322 | | function inverse(bool self) internal pure returns (string memory) { 323 | | return inverse(vm.toString(self)); 324 | | } 325 | | 326 | | function inverseBytes(bytes memory self) internal pure returns (string memory) { 327 | | return inverse(vm.toString(self)); 328 | | } 329 | | 330 | | function inverseBytes32(bytes32 self) internal pure returns (string memory) { 331 | | return inverse(vm.toString(self)); 332 | | } 333 | | } 334 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdToml.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.0 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | import {VmSafe} from "./Vm.sol"; 7 | | 8 | | // Helpers for parsing and writing TOML files 9 | | // To parse: 10 | | // ``` 11 | | // using stdToml for string; 12 | | // string memory toml = vm.readFile("<some_path>"); 13 | | // toml.readUint("<json_path>"); 14 | | // ``` 15 | | // To write: 16 | | // ``` 17 | | // using stdToml for string; 18 | | // string memory json = "json"; 19 | | // json.serialize("a", uint256(123)); 20 | | // string memory semiFinal = json.serialize("b", string("test")); 21 | | // string memory finalJson = json.serialize("c", semiFinal); 22 | | // finalJson.write("<some_path>"); 23 | | // ``` 24 | | 25 | * | library stdToml { 26 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 27 | | 28 | | function keyExists(string memory toml, string memory key) internal view returns (bool) { 29 | | return vm.keyExistsToml(toml, key); 30 | | } 31 | | 32 | | function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { 33 | | return vm.parseToml(toml, key); 34 | | } 35 | | 36 | | function readUint(string memory toml, string memory key) internal pure returns (uint256) { 37 | | return vm.parseTomlUint(toml, key); 38 | | } 39 | | 40 | | function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { 41 | | return vm.parseTomlUintArray(toml, key); 42 | | } 43 | | 44 | | function readInt(string memory toml, string memory key) internal pure returns (int256) { 45 | | return vm.parseTomlInt(toml, key); 46 | | } 47 | | 48 | | function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { 49 | | return vm.parseTomlIntArray(toml, key); 50 | | } 51 | | 52 | | function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { 53 | | return vm.parseTomlBytes32(toml, key); 54 | | } 55 | | 56 | | function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { 57 | | return vm.parseTomlBytes32Array(toml, key); 58 | | } 59 | | 60 | | function readString(string memory toml, string memory key) internal pure returns (string memory) { 61 | | return vm.parseTomlString(toml, key); 62 | | } 63 | | 64 | | function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { 65 | | return vm.parseTomlStringArray(toml, key); 66 | | } 67 | | 68 | | function readAddress(string memory toml, string memory key) internal pure returns (address) { 69 | | return vm.parseTomlAddress(toml, key); 70 | | } 71 | | 72 | | function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { 73 | | return vm.parseTomlAddressArray(toml, key); 74 | | } 75 | | 76 | | function readBool(string memory toml, string memory key) internal pure returns (bool) { 77 | | return vm.parseTomlBool(toml, key); 78 | | } 79 | | 80 | | function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { 81 | | return vm.parseTomlBoolArray(toml, key); 82 | | } 83 | | 84 | | function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { 85 | | return vm.parseTomlBytes(toml, key); 86 | | } 87 | | 88 | | function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { 89 | | return vm.parseTomlBytesArray(toml, key); 90 | | } 91 | | 92 | | function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { 93 | | return keyExists(toml, key) ? readUint(toml, key) : defaultValue; 94 | | } 95 | | 96 | | function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) 97 | | internal 98 | | view 99 | | returns (uint256[] memory) 100 | | { 101 | | return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; 102 | | } 103 | | 104 | | function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { 105 | | return keyExists(toml, key) ? readInt(toml, key) : defaultValue; 106 | | } 107 | | 108 | | function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) 109 | | internal 110 | | view 111 | | returns (int256[] memory) 112 | | { 113 | | return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; 114 | | } 115 | | 116 | | function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) 117 | | internal 118 | | view 119 | | returns (bytes32) 120 | | { 121 | | return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; 122 | | } 123 | | 124 | | function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) 125 | | internal 126 | | view 127 | | returns (bytes32[] memory) 128 | | { 129 | | return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; 130 | | } 131 | | 132 | | function readStringOr(string memory toml, string memory key, string memory defaultValue) 133 | | internal 134 | | view 135 | | returns (string memory) 136 | | { 137 | | return keyExists(toml, key) ? readString(toml, key) : defaultValue; 138 | | } 139 | | 140 | | function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) 141 | | internal 142 | | view 143 | | returns (string[] memory) 144 | | { 145 | | return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; 146 | | } 147 | | 148 | | function readAddressOr(string memory toml, string memory key, address defaultValue) 149 | | internal 150 | | view 151 | | returns (address) 152 | | { 153 | | return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; 154 | | } 155 | | 156 | | function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) 157 | | internal 158 | | view 159 | | returns (address[] memory) 160 | | { 161 | | return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; 162 | | } 163 | | 164 | | function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { 165 | | return keyExists(toml, key) ? readBool(toml, key) : defaultValue; 166 | | } 167 | | 168 | | function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) 169 | | internal 170 | | view 171 | | returns (bool[] memory) 172 | | { 173 | | return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; 174 | | } 175 | | 176 | | function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) 177 | | internal 178 | | view 179 | | returns (bytes memory) 180 | | { 181 | | return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; 182 | | } 183 | | 184 | | function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) 185 | | internal 186 | | view 187 | | returns (bytes[] memory) 188 | | { 189 | | return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; 190 | | } 191 | | 192 | | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { 193 | | return vm.serializeJson(jsonKey, rootObject); 194 | | } 195 | | 196 | | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { 197 | | return vm.serializeBool(jsonKey, key, value); 198 | | } 199 | | 200 | | function serialize(string memory jsonKey, string memory key, bool[] memory value) 201 | | internal 202 | | returns (string memory) 203 | | { 204 | | return vm.serializeBool(jsonKey, key, value); 205 | | } 206 | | 207 | | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { 208 | | return vm.serializeUint(jsonKey, key, value); 209 | | } 210 | | 211 | | function serialize(string memory jsonKey, string memory key, uint256[] memory value) 212 | | internal 213 | | returns (string memory) 214 | | { 215 | | return vm.serializeUint(jsonKey, key, value); 216 | | } 217 | | 218 | | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { 219 | | return vm.serializeInt(jsonKey, key, value); 220 | | } 221 | | 222 | | function serialize(string memory jsonKey, string memory key, int256[] memory value) 223 | | internal 224 | | returns (string memory) 225 | | { 226 | | return vm.serializeInt(jsonKey, key, value); 227 | | } 228 | | 229 | | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { 230 | | return vm.serializeAddress(jsonKey, key, value); 231 | | } 232 | | 233 | | function serialize(string memory jsonKey, string memory key, address[] memory value) 234 | | internal 235 | | returns (string memory) 236 | | { 237 | | return vm.serializeAddress(jsonKey, key, value); 238 | | } 239 | | 240 | | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { 241 | | return vm.serializeBytes32(jsonKey, key, value); 242 | | } 243 | | 244 | | function serialize(string memory jsonKey, string memory key, bytes32[] memory value) 245 | | internal 246 | | returns (string memory) 247 | | { 248 | | return vm.serializeBytes32(jsonKey, key, value); 249 | | } 250 | | 251 | | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { 252 | | return vm.serializeBytes(jsonKey, key, value); 253 | | } 254 | | 255 | | function serialize(string memory jsonKey, string memory key, bytes[] memory value) 256 | | internal 257 | | returns (string memory) 258 | | { 259 | | return vm.serializeBytes(jsonKey, key, value); 260 | | } 261 | | 262 | | function serialize(string memory jsonKey, string memory key, string memory value) 263 | | internal 264 | | returns (string memory) 265 | | { 266 | | return vm.serializeString(jsonKey, key, value); 267 | | } 268 | | 269 | | function serialize(string memory jsonKey, string memory key, string[] memory value) 270 | | internal 271 | | returns (string memory) 272 | | { 273 | | return vm.serializeString(jsonKey, key, value); 274 | | } 275 | | 276 | | function write(string memory jsonKey, string memory path) internal { 277 | | vm.writeToml(jsonKey, path); 278 | | } 279 | | 280 | | function write(string memory jsonKey, string memory path, string memory valueKey) internal { 281 | | vm.writeToml(jsonKey, path, valueKey); 282 | | } 283 | | } 284 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/StdUtils.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | import {IMulticall3} from "./interfaces/IMulticall3.sol"; 7 | | import {MockERC20} from "./mocks/MockERC20.sol"; 8 | | import {MockERC721} from "./mocks/MockERC721.sol"; 9 | | import {VmSafe} from "./Vm.sol"; 10 | | 11 | | abstract contract StdUtils { 12 | | /*////////////////////////////////////////////////////////////////////////// 13 | | CONSTANTS 14 | | //////////////////////////////////////////////////////////////////////////*/ 15 | | 16 | | IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); 17 | | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 18 | | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; 19 | | uint256 private constant INT256_MIN_ABS = 20 | | 57896044618658097711785492504343953926634992332820282019728792003956564819968; 21 | | uint256 private constant SECP256K1_ORDER = 22 | | 115792089237316195423570985008687907852837564279074904382605163141518161494337; 23 | | uint256 private constant UINT256_MAX = 24 | | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 25 | | 26 | | // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. 27 | | address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; 28 | | 29 | | /*////////////////////////////////////////////////////////////////////////// 30 | | INTERNAL FUNCTIONS 31 | | //////////////////////////////////////////////////////////////////////////*/ 32 | | 33 | | function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 34 | | require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); 35 | | // If x is between min and max, return x directly. This is to ensure that dictionary values 36 | | // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 37 | | if (x >= min && x <= max) return x; 38 | | 39 | | uint256 size = max - min + 1; 40 | | 41 | | // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. 42 | | // This helps ensure coverage of the min/max values. 43 | | if (x <= 3 && size > x) return min + x; 44 | | if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); 45 | | 46 | | // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. 47 | | if (x > max) { 48 | | uint256 diff = x - max; 49 | | uint256 rem = diff % size; 50 | | if (rem == 0) return max; 51 | | result = min + rem - 1; 52 | | } else if (x < min) { 53 | | uint256 diff = min - x; 54 | | uint256 rem = diff % size; 55 | | if (rem == 0) return min; 56 | | result = max - rem + 1; 57 | | } 58 | | } 59 | | 60 | | function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 61 | | result = _bound(x, min, max); 62 | | console2_log_StdUtils("Bound result", result); 63 | | } 64 | | 65 | | function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 66 | | require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); 67 | | 68 | | // Shifting all int256 values to uint256 to use _bound function. The range of two types are: 69 | | // int256 : -(2**255) ~ (2**255 - 1) 70 | | // uint256: 0 ~ (2**256 - 1) 71 | | // So, add 2**255, INT256_MIN_ABS to the integer values. 72 | | // 73 | | // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. 74 | | // So, use `~uint256(x) + 1` instead. 75 | | uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); 76 | | uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); 77 | | uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); 78 | | 79 | | uint256 y = _bound(_x, _min, _max); 80 | | 81 | | // To move it back to int256 value, subtract INT256_MIN_ABS at here. 82 | | result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); 83 | | } 84 | | 85 | | function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 86 | | result = _bound(x, min, max); 87 | | console2_log_StdUtils("Bound result", vm.toString(result)); 88 | | } 89 | | 90 | | function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { 91 | | result = _bound(privateKey, 1, SECP256K1_ORDER - 1); 92 | | } 93 | | 94 | | function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { 95 | | require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); 96 | | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); 97 | | } 98 | | 99 | | /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce 100 | | /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) 101 | | function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { 102 | | console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); 103 | | return vm.computeCreateAddress(deployer, nonce); 104 | | } 105 | | 106 | | function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) 107 | | internal 108 | | pure 109 | | virtual 110 | | returns (address) 111 | | { 112 | | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 113 | | return vm.computeCreate2Address(salt, initcodeHash, deployer); 114 | | } 115 | | 116 | | /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer 117 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { 118 | | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 119 | | return vm.computeCreate2Address(salt, initCodeHash); 120 | | } 121 | | 122 | | /// @dev returns an initialized mock ERC20 contract 123 | | function deployMockERC20(string memory name, string memory symbol, uint8 decimals) 124 | | internal 125 | | returns (MockERC20 mock) 126 | | { 127 | | mock = new MockERC20(); 128 | | mock.initialize(name, symbol, decimals); 129 | | } 130 | | 131 | | /// @dev returns an initialized mock ERC721 contract 132 | | function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { 133 | | mock = new MockERC721(); 134 | | mock.initialize(name, symbol); 135 | | } 136 | | 137 | | /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments 138 | | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 139 | | function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { 140 | | return hashInitCode(creationCode, ""); 141 | | } 142 | | 143 | | /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 144 | | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 145 | | /// @param args the ABI-encoded arguments to the constructor of C 146 | | function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { 147 | | return keccak256(abi.encodePacked(creationCode, args)); 148 | | } 149 | | 150 | | // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. 151 | | function getTokenBalances(address token, address[] memory addresses) 152 | | internal 153 | | virtual 154 | | returns (uint256[] memory balances) 155 | | { 156 | | uint256 tokenCodeSize; 157 | | assembly { 158 | | tokenCodeSize := extcodesize(token) 159 | | } 160 | | require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); 161 | | 162 | | // ABI encode the aggregate call to Multicall3. 163 | | uint256 length = addresses.length; 164 | | IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); 165 | | for (uint256 i = 0; i < length; ++i) { 166 | | // 0x70a08231 = bytes4("balanceOf(address)")) 167 | | calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); 168 | | } 169 | | 170 | | // Make the aggregate call. 171 | | (, bytes[] memory returnData) = multicall.aggregate(calls); 172 | | 173 | | // ABI decode the return data and return the balances. 174 | | balances = new uint256[](length); 175 | | for (uint256 i = 0; i < length; ++i) { 176 | | balances[i] = abi.decode(returnData[i], (uint256)); 177 | | } 178 | | } 179 | | 180 | | /*////////////////////////////////////////////////////////////////////////// 181 | | PRIVATE FUNCTIONS 182 | | //////////////////////////////////////////////////////////////////////////*/ 183 | | 184 | | function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { 185 | | return address(uint160(uint256(bytesValue))); 186 | | } 187 | | 188 | | // This section is used to prevent the compilation of console, which shortens the compilation time when console is 189 | | // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid 190 | | // any breaking changes to function signatures. 191 | | function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) 192 | | internal 193 | | pure 194 | | returns (function(bytes memory) internal pure fnOut) 195 | | { 196 | | assembly { 197 | | fnOut := fnIn 198 | | } 199 | | } 200 | | 201 | | function _sendLogPayload(bytes memory payload) internal pure { 202 | | _castLogPayloadViewToPure(_sendLogPayloadView)(payload); 203 | | } 204 | | 205 | | function _sendLogPayloadView(bytes memory payload) private view { 206 | | uint256 payloadLength = payload.length; 207 | | address consoleAddress = CONSOLE2_ADDRESS; 208 | | /// @solidity memory-safe-assembly 209 | | assembly { 210 | | let payloadStart := add(payload, 32) 211 | | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) 212 | | } 213 | | } 214 | | 215 | | function console2_log_StdUtils(string memory p0) private pure { 216 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 217 | | } 218 | | 219 | | function console2_log_StdUtils(string memory p0, uint256 p1) private pure { 220 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); 221 | | } 222 | | 223 | | function console2_log_StdUtils(string memory p0, string memory p1) private pure { 224 | | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 225 | | } 226 | | } 227 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Test.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | // 💬 ABOUT 7 | | // Forge Std's default Test. 8 | | 9 | | // 🧩 MODULES 10 | | import {console} from "./console.sol"; 11 | | import {console2} from "./console2.sol"; 12 | | import {safeconsole} from "./safeconsole.sol"; 13 | | import {StdAssertions} from "./StdAssertions.sol"; 14 | | import {StdChains} from "./StdChains.sol"; 15 | | import {StdCheats} from "./StdCheats.sol"; 16 | | import {stdError} from "./StdError.sol"; 17 | | import {StdInvariant} from "./StdInvariant.sol"; 18 | | import {stdJson} from "./StdJson.sol"; 19 | | import {stdMath} from "./StdMath.sol"; 20 | | import {StdStorage, stdStorage} from "./StdStorage.sol"; 21 | | import {StdStyle} from "./StdStyle.sol"; 22 | | import {stdToml} from "./StdToml.sol"; 23 | | import {StdUtils} from "./StdUtils.sol"; 24 | | import {Vm} from "./Vm.sol"; 25 | | 26 | | // 📦 BOILERPLATE 27 | | import {TestBase} from "./Base.sol"; 28 | | 29 | | // ⭐️ TEST 30 | | abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils { 31 | | // Note: IS_TEST() must return true. 32 | * | bool public IS_TEST = true; 33 | | } 34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/Vm.sol 1 | | // Automatically @generated by scripts/vm.py. Do not modify manually. 2 | | 3 | | // SPDX-License-Identifier: MIT OR Apache-2.0 4 | | pragma solidity >=0.6.2 <0.9.0; 5 | | pragma experimental ABIEncoderV2; 6 | | 7 | | /// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may 8 | | /// result in Script simulations differing from on-chain execution. It is recommended to only use 9 | | /// these cheats in scripts. 10 | | interface VmSafe { 11 | | /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`. 12 | | enum CallerMode { 13 | | // No caller modification is currently active. 14 | | None, 15 | | // A one time broadcast triggered by a `vm.broadcast()` call is currently active. 16 | | Broadcast, 17 | | // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active. 18 | | RecurrentBroadcast, 19 | | // A one time prank triggered by a `vm.prank()` call is currently active. 20 | | Prank, 21 | | // A recurrent prank triggered by a `vm.startPrank()` call is currently active. 22 | | RecurrentPrank 23 | | } 24 | | 25 | | /// The kind of account access that occurred. 26 | | enum AccountAccessKind { 27 | | // The account was called. 28 | | Call, 29 | | // The account was called via delegatecall. 30 | | DelegateCall, 31 | | // The account was called via callcode. 32 | | CallCode, 33 | | // The account was called via staticcall. 34 | | StaticCall, 35 | | // The account was created. 36 | | Create, 37 | | // The account was selfdestructed. 38 | | SelfDestruct, 39 | | // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess). 40 | | Resume, 41 | | // The account's balance was read. 42 | | Balance, 43 | | // The account's codesize was read. 44 | | Extcodesize, 45 | | // The account's codehash was read. 46 | | Extcodehash, 47 | | // The account's code was copied. 48 | | Extcodecopy 49 | | } 50 | | 51 | | /// Forge execution contexts. 52 | | enum ForgeContext { 53 | | // Test group execution context (test, coverage or snapshot). 54 | | TestGroup, 55 | | // `forge test` execution context. 56 | | Test, 57 | | // `forge coverage` execution context. 58 | | Coverage, 59 | | // `forge snapshot` execution context. 60 | | Snapshot, 61 | | // Script group execution context (dry run, broadcast or resume). 62 | | ScriptGroup, 63 | | // `forge script` execution context. 64 | | ScriptDryRun, 65 | | // `forge script --broadcast` execution context. 66 | | ScriptBroadcast, 67 | | // `forge script --resume` execution context. 68 | | ScriptResume, 69 | | // Unknown `forge` execution context. 70 | | Unknown 71 | | } 72 | | 73 | | /// An Ethereum log. Returned by `getRecordedLogs`. 74 | | struct Log { 75 | | // The topics of the log, including the signature, if any. 76 | | bytes32[] topics; 77 | | // The raw data of the log. 78 | | bytes data; 79 | | // The address of the log's emitter. 80 | | address emitter; 81 | | } 82 | | 83 | | /// An RPC URL and its alias. Returned by `rpcUrlStructs`. 84 | | struct Rpc { 85 | | // The alias of the RPC URL. 86 | | string key; 87 | | // The RPC URL. 88 | | string url; 89 | | } 90 | | 91 | | /// An RPC log object. Returned by `eth_getLogs`. 92 | | struct EthGetLogs { 93 | | // The address of the log's emitter. 94 | | address emitter; 95 | | // The topics of the log, including the signature, if any. 96 | | bytes32[] topics; 97 | | // The raw data of the log. 98 | | bytes data; 99 | | // The block hash. 100 | | bytes32 blockHash; 101 | | // The block number. 102 | | uint64 blockNumber; 103 | | // The transaction hash. 104 | | bytes32 transactionHash; 105 | | // The transaction index in the block. 106 | | uint64 transactionIndex; 107 | | // The log index. 108 | | uint256 logIndex; 109 | | // Whether the log was removed. 110 | | bool removed; 111 | | } 112 | | 113 | | /// A single entry in a directory listing. Returned by `readDir`. 114 | | struct DirEntry { 115 | | // The error message, if any. 116 | | string errorMessage; 117 | | // The path of the entry. 118 | | string path; 119 | | // The depth of the entry. 120 | | uint64 depth; 121 | | // Whether the entry is a directory. 122 | | bool isDir; 123 | | // Whether the entry is a symlink. 124 | | bool isSymlink; 125 | | } 126 | | 127 | | /// Metadata information about a file. 128 | | /// This structure is returned from the `fsMetadata` function and represents known 129 | | /// metadata about a file such as its permissions, size, modification 130 | | /// times, etc. 131 | | struct FsMetadata { 132 | | // True if this metadata is for a directory. 133 | | bool isDir; 134 | | // True if this metadata is for a symlink. 135 | | bool isSymlink; 136 | | // The size of the file, in bytes, this metadata is for. 137 | | uint256 length; 138 | | // True if this metadata is for a readonly (unwritable) file. 139 | | bool readOnly; 140 | | // The last modification time listed in this metadata. 141 | | uint256 modified; 142 | | // The last access time of this metadata. 143 | | uint256 accessed; 144 | | // The creation time listed in this metadata. 145 | | uint256 created; 146 | | } 147 | | 148 | | /// A wallet with a public and private key. 149 | | struct Wallet { 150 | | // The wallet's address. 151 | | address addr; 152 | | // The wallet's public key `X`. 153 | | uint256 publicKeyX; 154 | | // The wallet's public key `Y`. 155 | | uint256 publicKeyY; 156 | | // The wallet's private key. 157 | | uint256 privateKey; 158 | | } 159 | | 160 | | /// The result of a `tryFfi` call. 161 | | struct FfiResult { 162 | | // The exit code of the call. 163 | | int32 exitCode; 164 | | // The optionally hex-decoded `stdout` data. 165 | | bytes stdout; 166 | | // The `stderr` data. 167 | | bytes stderr; 168 | | } 169 | | 170 | | /// Information on the chain and fork. 171 | | struct ChainInfo { 172 | | // The fork identifier. Set to zero if no fork is active. 173 | | uint256 forkId; 174 | | // The chain ID of the current fork. 175 | | uint256 chainId; 176 | | } 177 | | 178 | | /// The result of a `stopAndReturnStateDiff` call. 179 | | struct AccountAccess { 180 | | // The chain and fork the access occurred. 181 | | ChainInfo chainInfo; 182 | | // The kind of account access that determines what the account is. 183 | | // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee. 184 | | // If kind is Create, then the account is the newly created account. 185 | | // If kind is SelfDestruct, then the account is the selfdestruct recipient. 186 | | // If kind is a Resume, then account represents a account context that has resumed. 187 | | AccountAccessKind kind; 188 | | // The account that was accessed. 189 | | // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT. 190 | | address account; 191 | | // What accessed the account. 192 | | address accessor; 193 | | // If the account was initialized or empty prior to the access. 194 | | // An account is considered initialized if it has code, a 195 | | // non-zero nonce, or a non-zero balance. 196 | | bool initialized; 197 | | // The previous balance of the accessed account. 198 | | uint256 oldBalance; 199 | | // The potential new balance of the accessed account. 200 | | // That is, all balance changes are recorded here, even if reverts occurred. 201 | | uint256 newBalance; 202 | | // Code of the account deployed by CREATE. 203 | | bytes deployedCode; 204 | | // Value passed along with the account access 205 | | uint256 value; 206 | | // Input data provided to the CREATE or CALL 207 | | bytes data; 208 | | // If this access reverted in either the current or parent context. 209 | | bool reverted; 210 | | // An ordered list of storage accesses made during an account access operation. 211 | | StorageAccess[] storageAccesses; 212 | | // Call depth traversed during the recording of state differences 213 | | uint64 depth; 214 | | } 215 | | 216 | | /// The storage accessed during an `AccountAccess`. 217 | | struct StorageAccess { 218 | | // The account whose storage was accessed. 219 | | address account; 220 | | // The slot that was accessed. 221 | | bytes32 slot; 222 | | // If the access was a write. 223 | | bool isWrite; 224 | | // The previous value of the slot. 225 | | bytes32 previousValue; 226 | | // The new value of the slot. 227 | | bytes32 newValue; 228 | | // If the access was reverted. 229 | | bool reverted; 230 | | } 231 | | 232 | | /// Gas used. Returned by `lastCallGas`. 233 | | struct Gas { 234 | | // The gas limit of the call. 235 | | uint64 gasLimit; 236 | | // The total gas used. 237 | | uint64 gasTotalUsed; 238 | | // DEPRECATED: The amount of gas used for memory expansion. Ref: <https://github.com/foundry-rs/foundry/pull/7934#pullrequestreview-2069236939> 239 | | uint64 gasMemoryUsed; 240 | | // The amount of gas refunded. 241 | | int64 gasRefunded; 242 | | // The amount of gas remaining. 243 | | uint64 gasRemaining; 244 | | } 245 | | 246 | | // ======== Crypto ======== 247 | | 248 | | /// Derives a private key from the name, labels the account with that name, and returns the wallet. 249 | | function createWallet(string calldata walletLabel) external returns (Wallet memory wallet); 250 | | 251 | | /// Generates a wallet from the private key and returns the wallet. 252 | | function createWallet(uint256 privateKey) external returns (Wallet memory wallet); 253 | | 254 | | /// Generates a wallet from the private key, labels the account with that name, and returns the wallet. 255 | | function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet); 256 | | 257 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) 258 | | /// at the derivation path `m/44'/60'/0'/0/{index}`. 259 | | function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey); 260 | | 261 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) 262 | | /// at `{derivationPath}{index}`. 263 | | function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index) 264 | | external 265 | | pure 266 | | returns (uint256 privateKey); 267 | | 268 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language 269 | | /// at the derivation path `m/44'/60'/0'/0/{index}`. 270 | | function deriveKey(string calldata mnemonic, uint32 index, string calldata language) 271 | | external 272 | | pure 273 | | returns (uint256 privateKey); 274 | | 275 | | /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language 276 | | /// at `{derivationPath}{index}`. 277 | | function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) 278 | | external 279 | | pure 280 | | returns (uint256 privateKey); 281 | | 282 | | /// Derives secp256r1 public key from the provided `privateKey`. 283 | | function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY); 284 | | 285 | | /// Adds a private key to the local forge wallet and returns the address. 286 | | function rememberKey(uint256 privateKey) external returns (address keyAddr); 287 | | 288 | | /// Signs data with a `Wallet`. 289 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the 290 | | /// signature's `s` value, and the recovery id `v` in a single bytes32. 291 | | /// This format reduces the signature size from 65 to 64 bytes. 292 | | function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); 293 | | 294 | | /// Signs `digest` with `privateKey` using the secp256k1 curve. 295 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the 296 | | /// signature's `s` value, and the recovery id `v` in a single bytes32. 297 | | /// This format reduces the signature size from 65 to 64 bytes. 298 | | function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); 299 | | 300 | | /// Signs `digest` with signer provided to script using the secp256k1 curve. 301 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the 302 | | /// signature's `s` value, and the recovery id `v` in a single bytes32. 303 | | /// This format reduces the signature size from 65 to 64 bytes. 304 | | /// If `--sender` is provided, the signer with provided address is used, otherwise, 305 | | /// if exactly one signer is provided to the script, that signer is used. 306 | | /// Raises error if signer passed through `--sender` does not match any unlocked signers or 307 | | /// if `--sender` is not provided and not exactly one signer is passed to the script. 308 | | function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); 309 | | 310 | | /// Signs `digest` with signer provided to script using the secp256k1 curve. 311 | | /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the 312 | | /// signature's `s` value, and the recovery id `v` in a single bytes32. 313 | | /// This format reduces the signature size from 65 to 64 bytes. 314 | | /// Raises error if none of the signers passed into the script have provided address. 315 | | function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); 316 | | 317 | | /// Signs `digest` with `privateKey` using the secp256r1 curve. 318 | | function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); 319 | | 320 | | /// Signs data with a `Wallet`. 321 | | function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); 322 | | 323 | | /// Signs `digest` with `privateKey` using the secp256k1 curve. 324 | | function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); 325 | | 326 | | /// Signs `digest` with signer provided to script using the secp256k1 curve. 327 | | /// If `--sender` is provided, the signer with provided address is used, otherwise, 328 | | /// if exactly one signer is provided to the script, that signer is used. 329 | | /// Raises error if signer passed through `--sender` does not match any unlocked signers or 330 | | /// if `--sender` is not provided and not exactly one signer is passed to the script. 331 | | function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); 332 | | 333 | | /// Signs `digest` with signer provided to script using the secp256k1 curve. 334 | | /// Raises error if none of the signers passed into the script have provided address. 335 | | function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); 336 | | 337 | | // ======== Environment ======== 338 | | 339 | | /// Gets the environment variable `name` and parses it as `address`. 340 | | /// Reverts if the variable was not found or could not be parsed. 341 | | function envAddress(string calldata name) external view returns (address value); 342 | | 343 | | /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. 344 | | /// Reverts if the variable was not found or could not be parsed. 345 | | function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); 346 | | 347 | | /// Gets the environment variable `name` and parses it as `bool`. 348 | | /// Reverts if the variable was not found or could not be parsed. 349 | | function envBool(string calldata name) external view returns (bool value); 350 | | 351 | | /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. 352 | | /// Reverts if the variable was not found or could not be parsed. 353 | | function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value); 354 | | 355 | | /// Gets the environment variable `name` and parses it as `bytes32`. 356 | | /// Reverts if the variable was not found or could not be parsed. 357 | | function envBytes32(string calldata name) external view returns (bytes32 value); 358 | | 359 | | /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. 360 | | /// Reverts if the variable was not found or could not be parsed. 361 | | function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value); 362 | | 363 | | /// Gets the environment variable `name` and parses it as `bytes`. 364 | | /// Reverts if the variable was not found or could not be parsed. 365 | | function envBytes(string calldata name) external view returns (bytes memory value); 366 | | 367 | | /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. 368 | | /// Reverts if the variable was not found or could not be parsed. 369 | | function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value); 370 | | 371 | | /// Gets the environment variable `name` and returns true if it exists, else returns false. 372 | | function envExists(string calldata name) external view returns (bool result); 373 | | 374 | | /// Gets the environment variable `name` and parses it as `int256`. 375 | | /// Reverts if the variable was not found or could not be parsed. 376 | | function envInt(string calldata name) external view returns (int256 value); 377 | | 378 | | /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. 379 | | /// Reverts if the variable was not found or could not be parsed. 380 | | function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value); 381 | | 382 | | /// Gets the environment variable `name` and parses it as `bool`. 383 | | /// Reverts if the variable could not be parsed. 384 | | /// Returns `defaultValue` if the variable was not found. 385 | | function envOr(string calldata name, bool defaultValue) external view returns (bool value); 386 | | 387 | | /// Gets the environment variable `name` and parses it as `uint256`. 388 | | /// Reverts if the variable could not be parsed. 389 | | /// Returns `defaultValue` if the variable was not found. 390 | | function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value); 391 | | 392 | | /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`. 393 | | /// Reverts if the variable could not be parsed. 394 | | /// Returns `defaultValue` if the variable was not found. 395 | | function envOr(string calldata name, string calldata delim, address[] calldata defaultValue) 396 | | external 397 | | view 398 | | returns (address[] memory value); 399 | | 400 | | /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`. 401 | | /// Reverts if the variable could not be parsed. 402 | | /// Returns `defaultValue` if the variable was not found. 403 | | function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue) 404 | | external 405 | | view 406 | | returns (bytes32[] memory value); 407 | | 408 | | /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. 409 | | /// Reverts if the variable could not be parsed. 410 | | /// Returns `defaultValue` if the variable was not found. 411 | | function envOr(string calldata name, string calldata delim, string[] calldata defaultValue) 412 | | external 413 | | view 414 | | returns (string[] memory value); 415 | | 416 | | /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`. 417 | | /// Reverts if the variable could not be parsed. 418 | | /// Returns `defaultValue` if the variable was not found. 419 | | function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue) 420 | | external 421 | | view 422 | | returns (bytes[] memory value); 423 | | 424 | | /// Gets the environment variable `name` and parses it as `int256`. 425 | | /// Reverts if the variable could not be parsed. 426 | | /// Returns `defaultValue` if the variable was not found. 427 | | function envOr(string calldata name, int256 defaultValue) external view returns (int256 value); 428 | | 429 | | /// Gets the environment variable `name` and parses it as `address`. 430 | | /// Reverts if the variable could not be parsed. 431 | | /// Returns `defaultValue` if the variable was not found. 432 | | function envOr(string calldata name, address defaultValue) external view returns (address value); 433 | | 434 | | /// Gets the environment variable `name` and parses it as `bytes32`. 435 | | /// Reverts if the variable could not be parsed. 436 | | /// Returns `defaultValue` if the variable was not found. 437 | | function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value); 438 | | 439 | | /// Gets the environment variable `name` and parses it as `string`. 440 | | /// Reverts if the variable could not be parsed. 441 | | /// Returns `defaultValue` if the variable was not found. 442 | | function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value); 443 | | 444 | | /// Gets the environment variable `name` and parses it as `bytes`. 445 | | /// Reverts if the variable could not be parsed. 446 | | /// Returns `defaultValue` if the variable was not found. 447 | | function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value); 448 | | 449 | | /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`. 450 | | /// Reverts if the variable could not be parsed. 451 | | /// Returns `defaultValue` if the variable was not found. 452 | | function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue) 453 | | external 454 | | view 455 | | returns (bool[] memory value); 456 | | 457 | | /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. 458 | | /// Reverts if the variable could not be parsed. 459 | | /// Returns `defaultValue` if the variable was not found. 460 | | function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue) 461 | | external 462 | | view 463 | | returns (uint256[] memory value); 464 | | 465 | | /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`. 466 | | /// Reverts if the variable could not be parsed. 467 | | /// Returns `defaultValue` if the variable was not found. 468 | | function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue) 469 | | external 470 | | view 471 | | returns (int256[] memory value); 472 | | 473 | | /// Gets the environment variable `name` and parses it as `string`. 474 | | /// Reverts if the variable was not found or could not be parsed. 475 | | function envString(string calldata name) external view returns (string memory value); 476 | | 477 | | /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`. 478 | | /// Reverts if the variable was not found or could not be parsed. 479 | | function envString(string calldata name, string calldata delim) external view returns (string[] memory value); 480 | | 481 | | /// Gets the environment variable `name` and parses it as `uint256`. 482 | | /// Reverts if the variable was not found or could not be parsed. 483 | | function envUint(string calldata name) external view returns (uint256 value); 484 | | 485 | | /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`. 486 | | /// Reverts if the variable was not found or could not be parsed. 487 | | function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); 488 | | 489 | | /// Returns true if `forge` command was executed in given context. 490 | | function isContext(ForgeContext context) external view returns (bool result); 491 | | 492 | | /// Sets environment variables. 493 | | function setEnv(string calldata name, string calldata value) external; 494 | | 495 | | // ======== EVM ======== 496 | | 497 | | /// Gets all accessed reads and write slot from a `vm.record` session, for a given address. 498 | | function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots); 499 | | 500 | | /// Gets the address for a given private key. 501 | | function addr(uint256 privateKey) external pure returns (address keyAddr); 502 | | 503 | | /// Gets all the logs according to specified filter. 504 | | function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics) 505 | | external 506 | | returns (EthGetLogs[] memory logs); 507 | | 508 | | /// Gets the current `block.blobbasefee`. 509 | | /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction, 510 | | /// and as a result will get optimized out by the compiler. 511 | | /// See https://github.com/foundry-rs/foundry/issues/6180 512 | | function getBlobBaseFee() external view returns (uint256 blobBaseFee); 513 | | 514 | | /// Gets the current `block.number`. 515 | | /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction, 516 | | /// and as a result will get optimized out by the compiler. 517 | | /// See https://github.com/foundry-rs/foundry/issues/6180 518 | | function getBlockNumber() external view returns (uint256 height); 519 | | 520 | | /// Gets the current `block.timestamp`. 521 | | /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction, 522 | | /// and as a result will get optimized out by the compiler. 523 | | /// See https://github.com/foundry-rs/foundry/issues/6180 524 | | function getBlockTimestamp() external view returns (uint256 timestamp); 525 | | 526 | | /// Gets the map key and parent of a mapping at a given slot, for a given address. 527 | | function getMappingKeyAndParentOf(address target, bytes32 elementSlot) 528 | | external 529 | | returns (bool found, bytes32 key, bytes32 parent); 530 | | 531 | | /// Gets the number of elements in the mapping at the given slot, for a given address. 532 | | function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length); 533 | | 534 | | /// Gets the elements at index idx of the mapping at the given slot, for a given address. The 535 | | /// index must be less than the length of the mapping (i.e. the number of keys in the mapping). 536 | | function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value); 537 | | 538 | | /// Gets the nonce of an account. 539 | | function getNonce(address account) external view returns (uint64 nonce); 540 | | 541 | | /// Get the nonce of a `Wallet`. 542 | | function getNonce(Wallet calldata wallet) external returns (uint64 nonce); 543 | | 544 | | /// Gets all the recorded logs. 545 | | function getRecordedLogs() external returns (Log[] memory logs); 546 | | 547 | | /// Gets the gas used in the last call. 548 | | function lastCallGas() external view returns (Gas memory gas); 549 | | 550 | | /// Loads a storage slot from an address. 551 | | function load(address target, bytes32 slot) external view returns (bytes32 data); 552 | | 553 | | /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused. 554 | | function pauseGasMetering() external; 555 | | 556 | | /// Records all storage reads and writes. 557 | | function record() external; 558 | | 559 | | /// Record all the transaction logs. 560 | | function recordLogs() external; 561 | | 562 | | /// Reset gas metering (i.e. gas usage is set to gas limit). 563 | | function resetGasMetering() external; 564 | | 565 | | /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on. 566 | | function resumeGasMetering() external; 567 | | 568 | | /// Performs an Ethereum JSON-RPC request to the current fork URL. 569 | | function rpc(string calldata method, string calldata params) external returns (bytes memory data); 570 | | 571 | | /// Performs an Ethereum JSON-RPC request to the given endpoint. 572 | | function rpc(string calldata urlOrAlias, string calldata method, string calldata params) 573 | | external 574 | | returns (bytes memory data); 575 | | 576 | | /// Starts recording all map SSTOREs for later retrieval. 577 | | function startMappingRecording() external; 578 | | 579 | | /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order, 580 | | /// along with the context of the calls 581 | | function startStateDiffRecording() external; 582 | | 583 | | /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. 584 | | function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); 585 | | 586 | | /// Stops recording all map SSTOREs for later retrieval and clears the recorded data. 587 | | function stopMappingRecording() external; 588 | | 589 | | // ======== Filesystem ======== 590 | | 591 | | /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. 592 | | /// `path` is relative to the project root. 593 | | function closeFile(string calldata path) external; 594 | | 595 | | /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`. 596 | | /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`. 597 | | /// Both `from` and `to` are relative to the project root. 598 | | function copyFile(string calldata from, string calldata to) external returns (uint64 copied); 599 | | 600 | | /// Creates a new, empty directory at the provided path. 601 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases: 602 | | /// - User lacks permissions to modify `path`. 603 | | /// - A parent of the given path doesn't exist and `recursive` is false. 604 | | /// - `path` already exists and `recursive` is false. 605 | | /// `path` is relative to the project root. 606 | | function createDir(string calldata path, bool recursive) external; 607 | | 608 | | /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the 609 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. 610 | | function deployCode(string calldata artifactPath) external returns (address deployedAddress); 611 | | 612 | | /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the 613 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. 614 | | /// Additionally accepts abi-encoded constructor arguments. 615 | | function deployCode(string calldata artifactPath, bytes calldata constructorArgs) 616 | | external 617 | | returns (address deployedAddress); 618 | | 619 | | /// Returns true if the given path points to an existing entity, else returns false. 620 | | function exists(string calldata path) external returns (bool result); 621 | | 622 | | /// Performs a foreign function call via the terminal. 623 | | function ffi(string[] calldata commandInput) external returns (bytes memory result); 624 | | 625 | | /// Given a path, query the file system to get information about a file, directory, etc. 626 | | function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata); 627 | | 628 | | /// Gets the artifact path from code (aka. creation code). 629 | | function getArtifactPathByCode(bytes calldata code) external view returns (string memory path); 630 | | 631 | | /// Gets the artifact path from deployed code (aka. runtime code). 632 | | function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path); 633 | | 634 | | /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the 635 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. 636 | | function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); 637 | | 638 | | /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the 639 | | /// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional. 640 | | function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); 641 | | 642 | | /// Returns true if the path exists on disk and is pointing at a directory, else returns false. 643 | | function isDir(string calldata path) external returns (bool result); 644 | | 645 | | /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. 646 | | function isFile(string calldata path) external returns (bool result); 647 | | 648 | | /// Get the path of the current project root. 649 | | function projectRoot() external view returns (string memory path); 650 | | 651 | | /// Prompts the user for a string value in the terminal. 652 | | function prompt(string calldata promptText) external returns (string memory input); 653 | | 654 | | /// Prompts the user for an address in the terminal. 655 | | function promptAddress(string calldata promptText) external returns (address); 656 | | 657 | | /// Prompts the user for a hidden string value in the terminal. 658 | | function promptSecret(string calldata promptText) external returns (string memory input); 659 | | 660 | | /// Prompts the user for hidden uint256 in the terminal (usually pk). 661 | | function promptSecretUint(string calldata promptText) external returns (uint256); 662 | | 663 | | /// Prompts the user for uint256 in the terminal. 664 | | function promptUint(string calldata promptText) external returns (uint256); 665 | | 666 | | /// Reads the directory at the given path recursively, up to `maxDepth`. 667 | | /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned. 668 | | /// Follows symbolic links if `followLinks` is true. 669 | | function readDir(string calldata path) external view returns (DirEntry[] memory entries); 670 | | 671 | | /// See `readDir(string)`. 672 | | function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries); 673 | | 674 | | /// See `readDir(string)`. 675 | | function readDir(string calldata path, uint64 maxDepth, bool followLinks) 676 | | external 677 | | view 678 | | returns (DirEntry[] memory entries); 679 | | 680 | | /// Reads the entire content of file to string. `path` is relative to the project root. 681 | | function readFile(string calldata path) external view returns (string memory data); 682 | | 683 | | /// Reads the entire content of file as binary. `path` is relative to the project root. 684 | | function readFileBinary(string calldata path) external view returns (bytes memory data); 685 | | 686 | | /// Reads next line of file to string. 687 | | function readLine(string calldata path) external view returns (string memory line); 688 | | 689 | | /// Reads a symbolic link, returning the path that the link points to. 690 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases: 691 | | /// - `path` is not a symbolic link. 692 | | /// - `path` does not exist. 693 | | function readLink(string calldata linkPath) external view returns (string memory targetPath); 694 | | 695 | | /// Removes a directory at the provided path. 696 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases: 697 | | /// - `path` doesn't exist. 698 | | /// - `path` isn't a directory. 699 | | /// - User lacks permissions to modify `path`. 700 | | /// - The directory is not empty and `recursive` is false. 701 | | /// `path` is relative to the project root. 702 | | function removeDir(string calldata path, bool recursive) external; 703 | | 704 | | /// Removes a file from the filesystem. 705 | | /// This cheatcode will revert in the following situations, but is not limited to just these cases: 706 | | /// - `path` points to a directory. 707 | | /// - The file doesn't exist. 708 | | /// - The user lacks permissions to remove the file. 709 | | /// `path` is relative to the project root. 710 | | function removeFile(string calldata path) external; 711 | | 712 | | /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr. 713 | | function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); 714 | | 715 | | /// Returns the time since unix epoch in milliseconds. 716 | | function unixTime() external returns (uint256 milliseconds); 717 | | 718 | | /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. 719 | | /// `path` is relative to the project root. 720 | | function writeFile(string calldata path, string calldata data) external; 721 | | 722 | | /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. 723 | | /// `path` is relative to the project root. 724 | | function writeFileBinary(string calldata path, bytes calldata data) external; 725 | | 726 | | /// Writes line to file, creating a file if it does not exist. 727 | | /// `path` is relative to the project root. 728 | | function writeLine(string calldata path, string calldata data) external; 729 | | 730 | | // ======== JSON ======== 731 | | 732 | | /// Checks if `key` exists in a JSON object. 733 | | function keyExistsJson(string calldata json, string calldata key) external view returns (bool); 734 | | 735 | | /// Parses a string of JSON data at `key` and coerces it to `address`. 736 | | function parseJsonAddress(string calldata json, string calldata key) external pure returns (address); 737 | | 738 | | /// Parses a string of JSON data at `key` and coerces it to `address[]`. 739 | | function parseJsonAddressArray(string calldata json, string calldata key) 740 | | external 741 | | pure 742 | | returns (address[] memory); 743 | | 744 | | /// Parses a string of JSON data at `key` and coerces it to `bool`. 745 | | function parseJsonBool(string calldata json, string calldata key) external pure returns (bool); 746 | | 747 | | /// Parses a string of JSON data at `key` and coerces it to `bool[]`. 748 | | function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory); 749 | | 750 | | /// Parses a string of JSON data at `key` and coerces it to `bytes`. 751 | | function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory); 752 | | 753 | | /// Parses a string of JSON data at `key` and coerces it to `bytes32`. 754 | | function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32); 755 | | 756 | | /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`. 757 | | function parseJsonBytes32Array(string calldata json, string calldata key) 758 | | external 759 | | pure 760 | | returns (bytes32[] memory); 761 | | 762 | | /// Parses a string of JSON data at `key` and coerces it to `bytes[]`. 763 | | function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory); 764 | | 765 | | /// Parses a string of JSON data at `key` and coerces it to `int256`. 766 | | function parseJsonInt(string calldata json, string calldata key) external pure returns (int256); 767 | | 768 | | /// Parses a string of JSON data at `key` and coerces it to `int256[]`. 769 | | function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory); 770 | | 771 | | /// Returns an array of all the keys in a JSON object. 772 | | function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); 773 | | 774 | | /// Parses a string of JSON data at `key` and coerces it to `string`. 775 | | function parseJsonString(string calldata json, string calldata key) external pure returns (string memory); 776 | | 777 | | /// Parses a string of JSON data at `key` and coerces it to `string[]`. 778 | | function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory); 779 | | 780 | | /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`. 781 | | function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription) 782 | | external 783 | | pure 784 | | returns (bytes memory); 785 | | 786 | | /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`. 787 | | function parseJsonType(string calldata json, string calldata typeDescription) 788 | | external 789 | | pure 790 | | returns (bytes memory); 791 | | 792 | | /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`. 793 | | function parseJsonType(string calldata json, string calldata key, string calldata typeDescription) 794 | | external 795 | | pure 796 | | returns (bytes memory); 797 | | 798 | | /// Parses a string of JSON data at `key` and coerces it to `uint256`. 799 | | function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256); 800 | | 801 | | /// Parses a string of JSON data at `key` and coerces it to `uint256[]`. 802 | | function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory); 803 | | 804 | | /// ABI-encodes a JSON object. 805 | | function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData); 806 | | 807 | | /// ABI-encodes a JSON object at `key`. 808 | | function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData); 809 | | 810 | | /// See `serializeJson`. 811 | | function serializeAddress(string calldata objectKey, string calldata valueKey, address value) 812 | | external 813 | | returns (string memory json); 814 | | 815 | | /// See `serializeJson`. 816 | | function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values) 817 | | external 818 | | returns (string memory json); 819 | | 820 | | /// See `serializeJson`. 821 | | function serializeBool(string calldata objectKey, string calldata valueKey, bool value) 822 | | external 823 | | returns (string memory json); 824 | | 825 | | /// See `serializeJson`. 826 | | function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values) 827 | | external 828 | | returns (string memory json); 829 | | 830 | | /// See `serializeJson`. 831 | | function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value) 832 | | external 833 | | returns (string memory json); 834 | | 835 | | /// See `serializeJson`. 836 | | function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values) 837 | | external 838 | | returns (string memory json); 839 | | 840 | | /// See `serializeJson`. 841 | | function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value) 842 | | external 843 | | returns (string memory json); 844 | | 845 | | /// See `serializeJson`. 846 | | function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values) 847 | | external 848 | | returns (string memory json); 849 | | 850 | | /// See `serializeJson`. 851 | | function serializeInt(string calldata objectKey, string calldata valueKey, int256 value) 852 | | external 853 | | returns (string memory json); 854 | | 855 | | /// See `serializeJson`. 856 | | function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values) 857 | | external 858 | | returns (string memory json); 859 | | 860 | | /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file. 861 | | /// Returns the stringified version of the specific JSON file up to that moment. 862 | | function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json); 863 | | 864 | | /// See `serializeJson`. 865 | | function serializeJsonType(string calldata typeDescription, bytes calldata value) 866 | | external 867 | | pure 868 | | returns (string memory json); 869 | | 870 | | /// See `serializeJson`. 871 | | function serializeJsonType( 872 | | string calldata objectKey, 873 | | string calldata valueKey, 874 | | string calldata typeDescription, 875 | | bytes calldata value 876 | | ) external returns (string memory json); 877 | | 878 | | /// See `serializeJson`. 879 | | function serializeString(string calldata objectKey, string calldata valueKey, string calldata value) 880 | | external 881 | | returns (string memory json); 882 | | 883 | | /// See `serializeJson`. 884 | | function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values) 885 | | external 886 | | returns (string memory json); 887 | | 888 | | /// See `serializeJson`. 889 | | function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value) 890 | | external 891 | | returns (string memory json); 892 | | 893 | | /// See `serializeJson`. 894 | | function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value) 895 | | external 896 | | returns (string memory json); 897 | | 898 | | /// See `serializeJson`. 899 | | function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values) 900 | | external 901 | | returns (string memory json); 902 | | 903 | | /// Write a serialized JSON object to a file. If the file exists, it will be overwritten. 904 | | function writeJson(string calldata json, string calldata path) external; 905 | | 906 | | /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.> 907 | | /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing. 908 | | function writeJson(string calldata json, string calldata path, string calldata valueKey) external; 909 | | 910 | | /// Checks if `key` exists in a JSON object 911 | | /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions. 912 | | function keyExists(string calldata json, string calldata key) external view returns (bool); 913 | | 914 | | // ======== Scripting ======== 915 | | 916 | | /// Takes a signed transaction and broadcasts it to the network. 917 | | function broadcastRawTransaction(bytes calldata data) external; 918 | | 919 | | /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain. 920 | | /// Broadcasting address is determined by checking the following in order: 921 | | /// 1. If `--sender` argument was provided, that address is used. 922 | | /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. 923 | | /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. 924 | | function broadcast() external; 925 | | 926 | | /// Has the next call (at this call depth only) create a transaction with the address provided 927 | | /// as the sender that can later be signed and sent onchain. 928 | | function broadcast(address signer) external; 929 | | 930 | | /// Has the next call (at this call depth only) create a transaction with the private key 931 | | /// provided as the sender that can later be signed and sent onchain. 932 | | function broadcast(uint256 privateKey) external; 933 | | 934 | | /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. 935 | | /// Broadcasting address is determined by checking the following in order: 936 | | /// 1. If `--sender` argument was provided, that address is used. 937 | | /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used. 938 | | /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used. 939 | | function startBroadcast() external; 940 | | 941 | | /// Has all subsequent calls (at this call depth only) create transactions with the address 942 | | /// provided that can later be signed and sent onchain. 943 | | function startBroadcast(address signer) external; 944 | | 945 | | /// Has all subsequent calls (at this call depth only) create transactions with the private key 946 | | /// provided that can later be signed and sent onchain. 947 | | function startBroadcast(uint256 privateKey) external; 948 | | 949 | | /// Stops collecting onchain transactions. 950 | | function stopBroadcast() external; 951 | | 952 | | // ======== String ======== 953 | | 954 | | /// Returns the index of the first occurrence of a `key` in an `input` string. 955 | | /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found. 956 | | /// Returns 0 in case of an empty `key`. 957 | | function indexOf(string calldata input, string calldata key) external pure returns (uint256); 958 | | 959 | | /// Parses the given `string` into an `address`. 960 | | function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue); 961 | | 962 | | /// Parses the given `string` into a `bool`. 963 | | function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue); 964 | | 965 | | /// Parses the given `string` into `bytes`. 966 | | function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue); 967 | | 968 | | /// Parses the given `string` into a `bytes32`. 969 | | function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue); 970 | | 971 | | /// Parses the given `string` into a `int256`. 972 | | function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue); 973 | | 974 | | /// Parses the given `string` into a `uint256`. 975 | | function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue); 976 | | 977 | | /// Replaces occurrences of `from` in the given `string` with `to`. 978 | | function replace(string calldata input, string calldata from, string calldata to) 979 | | external 980 | | pure 981 | | returns (string memory output); 982 | | 983 | | /// Splits the given `string` into an array of strings divided by the `delimiter`. 984 | | function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs); 985 | | 986 | | /// Converts the given `string` value to Lowercase. 987 | | function toLowercase(string calldata input) external pure returns (string memory output); 988 | | 989 | | /// Converts the given value to a `string`. 990 | | function toString(address value) external pure returns (string memory stringifiedValue); 991 | | 992 | | /// Converts the given value to a `string`. 993 | | function toString(bytes calldata value) external pure returns (string memory stringifiedValue); 994 | | 995 | | /// Converts the given value to a `string`. 996 | | function toString(bytes32 value) external pure returns (string memory stringifiedValue); 997 | | 998 | | /// Converts the given value to a `string`. 999 | | function toString(bool value) external pure returns (string memory stringifiedValue); 1000 | | 1001 | | /// Converts the given value to a `string`. 1002 | | function toString(uint256 value) external pure returns (string memory stringifiedValue); 1003 | | 1004 | | /// Converts the given value to a `string`. 1005 | | function toString(int256 value) external pure returns (string memory stringifiedValue); 1006 | | 1007 | | /// Converts the given `string` value to Uppercase. 1008 | | function toUppercase(string calldata input) external pure returns (string memory output); 1009 | | 1010 | | /// Trims leading and trailing whitespace from the given `string` value. 1011 | | function trim(string calldata input) external pure returns (string memory output); 1012 | | 1013 | | // ======== Testing ======== 1014 | | 1015 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. 1016 | | /// Formats values with decimals in failure message. 1017 | | function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure; 1018 | | 1019 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. 1020 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1021 | | function assertApproxEqAbsDecimal( 1022 | | uint256 left, 1023 | | uint256 right, 1024 | | uint256 maxDelta, 1025 | | uint256 decimals, 1026 | | string calldata error 1027 | | ) external pure; 1028 | | 1029 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. 1030 | | /// Formats values with decimals in failure message. 1031 | | function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure; 1032 | | 1033 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. 1034 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1035 | | function assertApproxEqAbsDecimal( 1036 | | int256 left, 1037 | | int256 right, 1038 | | uint256 maxDelta, 1039 | | uint256 decimals, 1040 | | string calldata error 1041 | | ) external pure; 1042 | | 1043 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. 1044 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure; 1045 | | 1046 | | /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`. 1047 | | /// Includes error message into revert string on failure. 1048 | | function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure; 1049 | | 1050 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. 1051 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure; 1052 | | 1053 | | /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`. 1054 | | /// Includes error message into revert string on failure. 1055 | | function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure; 1056 | | 1057 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1058 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1059 | | /// Formats values with decimals in failure message. 1060 | | function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals) 1061 | | external 1062 | | pure; 1063 | | 1064 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1065 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1066 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1067 | | function assertApproxEqRelDecimal( 1068 | | uint256 left, 1069 | | uint256 right, 1070 | | uint256 maxPercentDelta, 1071 | | uint256 decimals, 1072 | | string calldata error 1073 | | ) external pure; 1074 | | 1075 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1076 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1077 | | /// Formats values with decimals in failure message. 1078 | | function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals) 1079 | | external 1080 | | pure; 1081 | | 1082 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1083 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1084 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1085 | | function assertApproxEqRelDecimal( 1086 | | int256 left, 1087 | | int256 right, 1088 | | uint256 maxPercentDelta, 1089 | | uint256 decimals, 1090 | | string calldata error 1091 | | ) external pure; 1092 | | 1093 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1094 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1095 | | function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure; 1096 | | 1097 | | /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1098 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1099 | | /// Includes error message into revert string on failure. 1100 | | function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error) 1101 | | external 1102 | | pure; 1103 | | 1104 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1105 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1106 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure; 1107 | | 1108 | | /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`. 1109 | | /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100% 1110 | | /// Includes error message into revert string on failure. 1111 | | function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error) 1112 | | external 1113 | | pure; 1114 | | 1115 | | /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. 1116 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1117 | | 1118 | | /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message. 1119 | | /// Includes error message into revert string on failure. 1120 | | function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1121 | | 1122 | | /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. 1123 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure; 1124 | | 1125 | | /// Asserts that two `int256` values are equal, formatting them with decimals in failure message. 1126 | | /// Includes error message into revert string on failure. 1127 | | function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1128 | | 1129 | | /// Asserts that two `bool` values are equal. 1130 | | function assertEq(bool left, bool right) external pure; 1131 | | 1132 | | /// Asserts that two `bool` values are equal and includes error message into revert string on failure. 1133 | | function assertEq(bool left, bool right, string calldata error) external pure; 1134 | | 1135 | | /// Asserts that two `string` values are equal. 1136 | | function assertEq(string calldata left, string calldata right) external pure; 1137 | | 1138 | | /// Asserts that two `string` values are equal and includes error message into revert string on failure. 1139 | | function assertEq(string calldata left, string calldata right, string calldata error) external pure; 1140 | | 1141 | | /// Asserts that two `bytes` values are equal. 1142 | | function assertEq(bytes calldata left, bytes calldata right) external pure; 1143 | | 1144 | | /// Asserts that two `bytes` values are equal and includes error message into revert string on failure. 1145 | | function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure; 1146 | | 1147 | | /// Asserts that two arrays of `bool` values are equal. 1148 | | function assertEq(bool[] calldata left, bool[] calldata right) external pure; 1149 | | 1150 | | /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure. 1151 | | function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; 1152 | | 1153 | | /// Asserts that two arrays of `uint256 values are equal. 1154 | | function assertEq(uint256[] calldata left, uint256[] calldata right) external pure; 1155 | | 1156 | | /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure. 1157 | | function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; 1158 | | 1159 | | /// Asserts that two arrays of `int256` values are equal. 1160 | | function assertEq(int256[] calldata left, int256[] calldata right) external pure; 1161 | | 1162 | | /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure. 1163 | | function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; 1164 | | 1165 | | /// Asserts that two `uint256` values are equal. 1166 | | function assertEq(uint256 left, uint256 right) external pure; 1167 | | 1168 | | /// Asserts that two arrays of `address` values are equal. 1169 | | function assertEq(address[] calldata left, address[] calldata right) external pure; 1170 | | 1171 | | /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure. 1172 | | function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure; 1173 | | 1174 | | /// Asserts that two arrays of `bytes32` values are equal. 1175 | | function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure; 1176 | | 1177 | | /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure. 1178 | | function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; 1179 | | 1180 | | /// Asserts that two arrays of `string` values are equal. 1181 | | function assertEq(string[] calldata left, string[] calldata right) external pure; 1182 | | 1183 | | /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure. 1184 | | function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure; 1185 | | 1186 | | /// Asserts that two arrays of `bytes` values are equal. 1187 | | function assertEq(bytes[] calldata left, bytes[] calldata right) external pure; 1188 | | 1189 | | /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure. 1190 | | function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; 1191 | | 1192 | | /// Asserts that two `uint256` values are equal and includes error message into revert string on failure. 1193 | | function assertEq(uint256 left, uint256 right, string calldata error) external pure; 1194 | | 1195 | | /// Asserts that two `int256` values are equal. 1196 | | function assertEq(int256 left, int256 right) external pure; 1197 | | 1198 | | /// Asserts that two `int256` values are equal and includes error message into revert string on failure. 1199 | | function assertEq(int256 left, int256 right, string calldata error) external pure; 1200 | | 1201 | | /// Asserts that two `address` values are equal. 1202 | | function assertEq(address left, address right) external pure; 1203 | | 1204 | | /// Asserts that two `address` values are equal and includes error message into revert string on failure. 1205 | | function assertEq(address left, address right, string calldata error) external pure; 1206 | | 1207 | | /// Asserts that two `bytes32` values are equal. 1208 | | function assertEq(bytes32 left, bytes32 right) external pure; 1209 | | 1210 | | /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure. 1211 | | function assertEq(bytes32 left, bytes32 right, string calldata error) external pure; 1212 | | 1213 | | /// Asserts that the given condition is false. 1214 | | function assertFalse(bool condition) external pure; 1215 | | 1216 | | /// Asserts that the given condition is false and includes error message into revert string on failure. 1217 | | function assertFalse(bool condition, string calldata error) external pure; 1218 | | 1219 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second. 1220 | | /// Formats values with decimals in failure message. 1221 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1222 | | 1223 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second. 1224 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1225 | | function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1226 | | 1227 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second. 1228 | | /// Formats values with decimals in failure message. 1229 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure; 1230 | | 1231 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second. 1232 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1233 | | function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1234 | | 1235 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second. 1236 | | function assertGe(uint256 left, uint256 right) external pure; 1237 | | 1238 | | /// Compares two `uint256` values. Expects first value to be greater than or equal to second. 1239 | | /// Includes error message into revert string on failure. 1240 | | function assertGe(uint256 left, uint256 right, string calldata error) external pure; 1241 | | 1242 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second. 1243 | | function assertGe(int256 left, int256 right) external pure; 1244 | | 1245 | | /// Compares two `int256` values. Expects first value to be greater than or equal to second. 1246 | | /// Includes error message into revert string on failure. 1247 | | function assertGe(int256 left, int256 right, string calldata error) external pure; 1248 | | 1249 | | /// Compares two `uint256` values. Expects first value to be greater than second. 1250 | | /// Formats values with decimals in failure message. 1251 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1252 | | 1253 | | /// Compares two `uint256` values. Expects first value to be greater than second. 1254 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1255 | | function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1256 | | 1257 | | /// Compares two `int256` values. Expects first value to be greater than second. 1258 | | /// Formats values with decimals in failure message. 1259 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure; 1260 | | 1261 | | /// Compares two `int256` values. Expects first value to be greater than second. 1262 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1263 | | function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1264 | | 1265 | | /// Compares two `uint256` values. Expects first value to be greater than second. 1266 | | function assertGt(uint256 left, uint256 right) external pure; 1267 | | 1268 | | /// Compares two `uint256` values. Expects first value to be greater than second. 1269 | | /// Includes error message into revert string on failure. 1270 | | function assertGt(uint256 left, uint256 right, string calldata error) external pure; 1271 | | 1272 | | /// Compares two `int256` values. Expects first value to be greater than second. 1273 | | function assertGt(int256 left, int256 right) external pure; 1274 | | 1275 | | /// Compares two `int256` values. Expects first value to be greater than second. 1276 | | /// Includes error message into revert string on failure. 1277 | | function assertGt(int256 left, int256 right, string calldata error) external pure; 1278 | | 1279 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second. 1280 | | /// Formats values with decimals in failure message. 1281 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1282 | | 1283 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second. 1284 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1285 | | function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1286 | | 1287 | | /// Compares two `int256` values. Expects first value to be less than or equal to second. 1288 | | /// Formats values with decimals in failure message. 1289 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure; 1290 | | 1291 | | /// Compares two `int256` values. Expects first value to be less than or equal to second. 1292 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1293 | | function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1294 | | 1295 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second. 1296 | | function assertLe(uint256 left, uint256 right) external pure; 1297 | | 1298 | | /// Compares two `uint256` values. Expects first value to be less than or equal to second. 1299 | | /// Includes error message into revert string on failure. 1300 | | function assertLe(uint256 left, uint256 right, string calldata error) external pure; 1301 | | 1302 | | /// Compares two `int256` values. Expects first value to be less than or equal to second. 1303 | | function assertLe(int256 left, int256 right) external pure; 1304 | | 1305 | | /// Compares two `int256` values. Expects first value to be less than or equal to second. 1306 | | /// Includes error message into revert string on failure. 1307 | | function assertLe(int256 left, int256 right, string calldata error) external pure; 1308 | | 1309 | | /// Compares two `uint256` values. Expects first value to be less than second. 1310 | | /// Formats values with decimals in failure message. 1311 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1312 | | 1313 | | /// Compares two `uint256` values. Expects first value to be less than second. 1314 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1315 | | function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1316 | | 1317 | | /// Compares two `int256` values. Expects first value to be less than second. 1318 | | /// Formats values with decimals in failure message. 1319 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure; 1320 | | 1321 | | /// Compares two `int256` values. Expects first value to be less than second. 1322 | | /// Formats values with decimals in failure message. Includes error message into revert string on failure. 1323 | | function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1324 | | 1325 | | /// Compares two `uint256` values. Expects first value to be less than second. 1326 | | function assertLt(uint256 left, uint256 right) external pure; 1327 | | 1328 | | /// Compares two `uint256` values. Expects first value to be less than second. 1329 | | /// Includes error message into revert string on failure. 1330 | | function assertLt(uint256 left, uint256 right, string calldata error) external pure; 1331 | | 1332 | | /// Compares two `int256` values. Expects first value to be less than second. 1333 | | function assertLt(int256 left, int256 right) external pure; 1334 | | 1335 | | /// Compares two `int256` values. Expects first value to be less than second. 1336 | | /// Includes error message into revert string on failure. 1337 | | function assertLt(int256 left, int256 right, string calldata error) external pure; 1338 | | 1339 | | /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. 1340 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure; 1341 | | 1342 | | /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message. 1343 | | /// Includes error message into revert string on failure. 1344 | | function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure; 1345 | | 1346 | | /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. 1347 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure; 1348 | | 1349 | | /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message. 1350 | | /// Includes error message into revert string on failure. 1351 | | function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure; 1352 | | 1353 | | /// Asserts that two `bool` values are not equal. 1354 | | function assertNotEq(bool left, bool right) external pure; 1355 | | 1356 | | /// Asserts that two `bool` values are not equal and includes error message into revert string on failure. 1357 | | function assertNotEq(bool left, bool right, string calldata error) external pure; 1358 | | 1359 | | /// Asserts that two `string` values are not equal. 1360 | | function assertNotEq(string calldata left, string calldata right) external pure; 1361 | | 1362 | | /// Asserts that two `string` values are not equal and includes error message into revert string on failure. 1363 | | function assertNotEq(string calldata left, string calldata right, string calldata error) external pure; 1364 | | 1365 | | /// Asserts that two `bytes` values are not equal. 1366 | | function assertNotEq(bytes calldata left, bytes calldata right) external pure; 1367 | | 1368 | | /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure. 1369 | | function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure; 1370 | | 1371 | | /// Asserts that two arrays of `bool` values are not equal. 1372 | | function assertNotEq(bool[] calldata left, bool[] calldata right) external pure; 1373 | | 1374 | | /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure. 1375 | | function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure; 1376 | | 1377 | | /// Asserts that two arrays of `uint256` values are not equal. 1378 | | function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure; 1379 | | 1380 | | /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure. 1381 | | function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure; 1382 | | 1383 | | /// Asserts that two arrays of `int256` values are not equal. 1384 | | function assertNotEq(int256[] calldata left, int256[] calldata right) external pure; 1385 | | 1386 | | /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure. 1387 | | function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure; 1388 | | 1389 | | /// Asserts that two `uint256` values are not equal. 1390 | | function assertNotEq(uint256 left, uint256 right) external pure; 1391 | | 1392 | | /// Asserts that two arrays of `address` values are not equal. 1393 | | function assertNotEq(address[] calldata left, address[] calldata right) external pure; 1394 | | 1395 | | /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure. 1396 | | function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure; 1397 | | 1398 | | /// Asserts that two arrays of `bytes32` values are not equal. 1399 | | function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure; 1400 | | 1401 | | /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure. 1402 | | function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure; 1403 | | 1404 | | /// Asserts that two arrays of `string` values are not equal. 1405 | | function assertNotEq(string[] calldata left, string[] calldata right) external pure; 1406 | | 1407 | | /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure. 1408 | | function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure; 1409 | | 1410 | | /// Asserts that two arrays of `bytes` values are not equal. 1411 | | function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure; 1412 | | 1413 | | /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure. 1414 | | function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure; 1415 | | 1416 | | /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure. 1417 | | function assertNotEq(uint256 left, uint256 right, string calldata error) external pure; 1418 | | 1419 | | /// Asserts that two `int256` values are not equal. 1420 | | function assertNotEq(int256 left, int256 right) external pure; 1421 | | 1422 | | /// Asserts that two `int256` values are not equal and includes error message into revert string on failure. 1423 | | function assertNotEq(int256 left, int256 right, string calldata error) external pure; 1424 | | 1425 | | /// Asserts that two `address` values are not equal. 1426 | | function assertNotEq(address left, address right) external pure; 1427 | | 1428 | | /// Asserts that two `address` values are not equal and includes error message into revert string on failure. 1429 | | function assertNotEq(address left, address right, string calldata error) external pure; 1430 | | 1431 | | /// Asserts that two `bytes32` values are not equal. 1432 | | function assertNotEq(bytes32 left, bytes32 right) external pure; 1433 | | 1434 | | /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure. 1435 | | function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure; 1436 | | 1437 | | /// Asserts that the given condition is true. 1438 | | function assertTrue(bool condition) external pure; 1439 | | 1440 | | /// Asserts that the given condition is true and includes error message into revert string on failure. 1441 | | function assertTrue(bool condition, string calldata error) external pure; 1442 | | 1443 | | /// If the condition is false, discard this run's fuzz inputs and generate new ones. 1444 | | function assume(bool condition) external pure; 1445 | | 1446 | | /// Discard this run's fuzz inputs and generate new ones if next call reverted. 1447 | | function assumeNoRevert() external pure; 1448 | | 1449 | | /// Writes a breakpoint to jump to in the debugger. 1450 | | function breakpoint(string calldata char) external; 1451 | | 1452 | | /// Writes a conditional breakpoint to jump to in the debugger. 1453 | | function breakpoint(string calldata char, bool value) external; 1454 | | 1455 | | /// Returns the Foundry version. 1456 | | /// Format: <cargo_version>+<git_sha>+<build_timestamp> 1457 | | /// Sample output: 0.2.0+faa94c384+202407110019 1458 | | /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs. 1459 | | /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000) 1460 | | /// to compare timestamps while ignoring minor time differences. 1461 | | function getFoundryVersion() external view returns (string memory version); 1462 | | 1463 | | /// Returns the RPC url for the given alias. 1464 | | function rpcUrl(string calldata rpcAlias) external view returns (string memory json); 1465 | | 1466 | | /// Returns all rpc urls and their aliases as structs. 1467 | | function rpcUrlStructs() external view returns (Rpc[] memory urls); 1468 | | 1469 | | /// Returns all rpc urls and their aliases `[alias, url][]`. 1470 | | function rpcUrls() external view returns (string[2][] memory urls); 1471 | | 1472 | | /// Suspends execution of the main thread for `duration` milliseconds. 1473 | | function sleep(uint256 duration) external; 1474 | | 1475 | | // ======== Toml ======== 1476 | | 1477 | | /// Checks if `key` exists in a TOML table. 1478 | | function keyExistsToml(string calldata toml, string calldata key) external view returns (bool); 1479 | | 1480 | | /// Parses a string of TOML data at `key` and coerces it to `address`. 1481 | | function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address); 1482 | | 1483 | | /// Parses a string of TOML data at `key` and coerces it to `address[]`. 1484 | | function parseTomlAddressArray(string calldata toml, string calldata key) 1485 | | external 1486 | | pure 1487 | | returns (address[] memory); 1488 | | 1489 | | /// Parses a string of TOML data at `key` and coerces it to `bool`. 1490 | | function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool); 1491 | | 1492 | | /// Parses a string of TOML data at `key` and coerces it to `bool[]`. 1493 | | function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory); 1494 | | 1495 | | /// Parses a string of TOML data at `key` and coerces it to `bytes`. 1496 | | function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory); 1497 | | 1498 | | /// Parses a string of TOML data at `key` and coerces it to `bytes32`. 1499 | | function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32); 1500 | | 1501 | | /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`. 1502 | | function parseTomlBytes32Array(string calldata toml, string calldata key) 1503 | | external 1504 | | pure 1505 | | returns (bytes32[] memory); 1506 | | 1507 | | /// Parses a string of TOML data at `key` and coerces it to `bytes[]`. 1508 | | function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory); 1509 | | 1510 | | /// Parses a string of TOML data at `key` and coerces it to `int256`. 1511 | | function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256); 1512 | | 1513 | | /// Parses a string of TOML data at `key` and coerces it to `int256[]`. 1514 | | function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory); 1515 | | 1516 | | /// Returns an array of all the keys in a TOML table. 1517 | | function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys); 1518 | | 1519 | | /// Parses a string of TOML data at `key` and coerces it to `string`. 1520 | | function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory); 1521 | | 1522 | | /// Parses a string of TOML data at `key` and coerces it to `string[]`. 1523 | | function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory); 1524 | | 1525 | | /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`. 1526 | | function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription) 1527 | | external 1528 | | pure 1529 | | returns (bytes memory); 1530 | | 1531 | | /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`. 1532 | | function parseTomlType(string calldata toml, string calldata typeDescription) 1533 | | external 1534 | | pure 1535 | | returns (bytes memory); 1536 | | 1537 | | /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`. 1538 | | function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription) 1539 | | external 1540 | | pure 1541 | | returns (bytes memory); 1542 | | 1543 | | /// Parses a string of TOML data at `key` and coerces it to `uint256`. 1544 | | function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256); 1545 | | 1546 | | /// Parses a string of TOML data at `key` and coerces it to `uint256[]`. 1547 | | function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory); 1548 | | 1549 | | /// ABI-encodes a TOML table. 1550 | | function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData); 1551 | | 1552 | | /// ABI-encodes a TOML table at `key`. 1553 | | function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData); 1554 | | 1555 | | /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file. 1556 | | function writeToml(string calldata json, string calldata path) external; 1557 | | 1558 | | /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.> 1559 | | /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing. 1560 | | function writeToml(string calldata json, string calldata path, string calldata valueKey) external; 1561 | | 1562 | | // ======== Utilities ======== 1563 | | 1564 | | /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer. 1565 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer) 1566 | | external 1567 | | pure 1568 | | returns (address); 1569 | | 1570 | | /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer. 1571 | | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address); 1572 | | 1573 | | /// Compute the address a contract will be deployed at for a given deployer address and nonce. 1574 | | function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address); 1575 | | 1576 | | /// Utility cheatcode to copy storage of `from` contract to another `to` contract. 1577 | | function copyStorage(address from, address to) external; 1578 | | 1579 | | /// Returns ENS namehash for provided string. 1580 | | function ensNamehash(string calldata name) external pure returns (bytes32); 1581 | | 1582 | | /// Gets the label for the specified address. 1583 | | function getLabel(address account) external view returns (string memory currentLabel); 1584 | | 1585 | | /// Labels an address in call traces. 1586 | | function label(address account, string calldata newLabel) external; 1587 | | 1588 | | /// Pauses collection of call traces. Useful in cases when you want to skip tracing of 1589 | | /// complex calls which are not useful for debugging. 1590 | | function pauseTracing() external view; 1591 | | 1592 | | /// Returns a random `address`. 1593 | | function randomAddress() external returns (address); 1594 | | 1595 | | /// Returns an random `bool`. 1596 | | function randomBool() external view returns (bool); 1597 | | 1598 | | /// Returns an random byte array value of the given length. 1599 | | function randomBytes(uint256 len) external view returns (bytes memory); 1600 | | 1601 | | /// Returns an random `int256` value. 1602 | | function randomInt() external view returns (int256); 1603 | | 1604 | | /// Returns an random `int256` value of given bits. 1605 | | function randomInt(uint256 bits) external view returns (int256); 1606 | | 1607 | | /// Returns a random uint256 value. 1608 | | function randomUint() external returns (uint256); 1609 | | 1610 | | /// Returns random uint256 value between the provided range (=min..=max). 1611 | | function randomUint(uint256 min, uint256 max) external returns (uint256); 1612 | | 1613 | | /// Returns an random `uint256` value of given bits. 1614 | | function randomUint(uint256 bits) external view returns (uint256); 1615 | | 1616 | | /// Unpauses collection of call traces. 1617 | | function resumeTracing() external view; 1618 | | 1619 | | /// Utility cheatcode to set arbitrary storage for given target address. 1620 | | function setArbitraryStorage(address target) external; 1621 | | 1622 | | /// Encodes a `bytes` value to a base64url string. 1623 | | function toBase64URL(bytes calldata data) external pure returns (string memory); 1624 | | 1625 | | /// Encodes a `string` value to a base64url string. 1626 | | function toBase64URL(string calldata data) external pure returns (string memory); 1627 | | 1628 | | /// Encodes a `bytes` value to a base64 string. 1629 | | function toBase64(bytes calldata data) external pure returns (string memory); 1630 | | 1631 | | /// Encodes a `string` value to a base64 string. 1632 | | function toBase64(string calldata data) external pure returns (string memory); 1633 | | } 1634 | | 1635 | | /// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used 1636 | | /// in tests, but it is not recommended to use these cheats in scripts. 1637 | | interface Vm is VmSafe { 1638 | | // ======== EVM ======== 1639 | | 1640 | | /// Returns the identifier of the currently active fork. Reverts if no fork is currently active. 1641 | | function activeFork() external view returns (uint256 forkId); 1642 | | 1643 | | /// In forking mode, explicitly grant the given address cheatcode access. 1644 | | function allowCheatcodes(address account) external; 1645 | | 1646 | | /// Sets `block.blobbasefee` 1647 | | function blobBaseFee(uint256 newBlobBaseFee) external; 1648 | | 1649 | | /// Sets the blobhashes in the transaction. 1650 | | /// Not available on EVM versions before Cancun. 1651 | | /// If used on unsupported EVM versions it will revert. 1652 | | function blobhashes(bytes32[] calldata hashes) external; 1653 | | 1654 | | /// Sets `block.chainid`. 1655 | | function chainId(uint256 newChainId) external; 1656 | | 1657 | | /// Clears all mocked calls. 1658 | | function clearMockedCalls() external; 1659 | | 1660 | | /// Sets `block.coinbase`. 1661 | | function coinbase(address newCoinbase) external; 1662 | | 1663 | | /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork. 1664 | | function createFork(string calldata urlOrAlias) external returns (uint256 forkId); 1665 | | 1666 | | /// Creates a new fork with the given endpoint and block and returns the identifier of the fork. 1667 | | function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); 1668 | | 1669 | | /// Creates a new fork with the given endpoint and at the block the given transaction was mined in, 1670 | | /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork. 1671 | | function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); 1672 | | 1673 | | /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork. 1674 | | function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId); 1675 | | 1676 | | /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork. 1677 | | function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId); 1678 | | 1679 | | /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in, 1680 | | /// replays all transaction mined in the block before the transaction, returns the identifier of the fork. 1681 | | function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId); 1682 | | 1683 | | /// Sets an address' balance. 1684 | | function deal(address account, uint256 newBalance) external; 1685 | | 1686 | | /// Removes the snapshot with the given ID created by `snapshot`. 1687 | | /// Takes the snapshot ID to delete. 1688 | | /// Returns `true` if the snapshot was successfully deleted. 1689 | | /// Returns `false` if the snapshot does not exist. 1690 | | function deleteSnapshot(uint256 snapshotId) external returns (bool success); 1691 | | 1692 | | /// Removes _all_ snapshots previously created by `snapshot`. 1693 | | function deleteSnapshots() external; 1694 | | 1695 | | /// Sets `block.difficulty`. 1696 | | /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. 1697 | | /// Reverts if used on unsupported EVM versions. 1698 | | function difficulty(uint256 newDifficulty) external; 1699 | | 1700 | | /// Dump a genesis JSON file's `allocs` to disk. 1701 | | function dumpState(string calldata pathToStateJson) external; 1702 | | 1703 | | /// Sets an address' code. 1704 | | function etch(address target, bytes calldata newRuntimeBytecode) external; 1705 | | 1706 | | /// Sets `block.basefee`. 1707 | | function fee(uint256 newBasefee) external; 1708 | | 1709 | | /// Gets the blockhashes from the current transaction. 1710 | | /// Not available on EVM versions before Cancun. 1711 | | /// If used on unsupported EVM versions it will revert. 1712 | | function getBlobhashes() external view returns (bytes32[] memory hashes); 1713 | | 1714 | | /// Returns true if the account is marked as persistent. 1715 | | function isPersistent(address account) external view returns (bool persistent); 1716 | | 1717 | | /// Load a genesis JSON file's `allocs` into the in-memory revm state. 1718 | | function loadAllocs(string calldata pathToAllocsJson) external; 1719 | | 1720 | | /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup 1721 | | /// Meaning, changes made to the state of this account will be kept when switching forks. 1722 | | function makePersistent(address account) external; 1723 | | 1724 | | /// See `makePersistent(address)`. 1725 | | function makePersistent(address account0, address account1) external; 1726 | | 1727 | | /// See `makePersistent(address)`. 1728 | | function makePersistent(address account0, address account1, address account2) external; 1729 | | 1730 | | /// See `makePersistent(address)`. 1731 | | function makePersistent(address[] calldata accounts) external; 1732 | | 1733 | | /// Reverts a call to an address with specified revert data. 1734 | | function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; 1735 | | 1736 | | /// Reverts a call to an address with a specific `msg.value`, with specified revert data. 1737 | | function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) 1738 | | external; 1739 | | 1740 | | /// Mocks a call to an address, returning specified data. 1741 | | /// Calldata can either be strict or a partial match, e.g. if you only 1742 | | /// pass a Solidity selector to the expected calldata, then the entire Solidity 1743 | | /// function will be mocked. 1744 | | function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; 1745 | | 1746 | | /// Mocks a call to an address with a specific `msg.value`, returning specified data. 1747 | | /// Calldata match takes precedence over `msg.value` in case of ambiguity. 1748 | | function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; 1749 | | 1750 | | /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls 1751 | | /// `target` with the same calldata. This functionality is similar to a delegate call made to 1752 | | /// `target` contract from `callee`. 1753 | | /// Can be used to substitute a call to a function with another implementation that captures 1754 | | /// the primary logic of the original function but is easier to reason about. 1755 | | /// If calldata is not a strict match then partial match by selector is attempted. 1756 | | function mockFunction(address callee, address target, bytes calldata data) external; 1757 | | 1758 | | /// Sets the *next* call's `msg.sender` to be the input address. 1759 | | function prank(address msgSender) external; 1760 | | 1761 | | /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. 1762 | | function prank(address msgSender, address txOrigin) external; 1763 | | 1764 | | /// Sets `block.prevrandao`. 1765 | | /// Not available on EVM versions before Paris. Use `difficulty` instead. 1766 | | /// If used on unsupported EVM versions it will revert. 1767 | | function prevrandao(bytes32 newPrevrandao) external; 1768 | | 1769 | | /// Sets `block.prevrandao`. 1770 | | /// Not available on EVM versions before Paris. Use `difficulty` instead. 1771 | | /// If used on unsupported EVM versions it will revert. 1772 | | function prevrandao(uint256 newPrevrandao) external; 1773 | | 1774 | | /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification. 1775 | | function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin); 1776 | | 1777 | | /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts. 1778 | | function resetNonce(address account) external; 1779 | | 1780 | | /// Revert the state of the EVM to a previous snapshot 1781 | | /// Takes the snapshot ID to revert to. 1782 | | /// Returns `true` if the snapshot was successfully reverted. 1783 | | /// Returns `false` if the snapshot does not exist. 1784 | | /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. 1785 | | function revertTo(uint256 snapshotId) external returns (bool success); 1786 | | 1787 | | /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots 1788 | | /// Takes the snapshot ID to revert to. 1789 | | /// Returns `true` if the snapshot was successfully reverted and deleted. 1790 | | /// Returns `false` if the snapshot does not exist. 1791 | | function revertToAndDelete(uint256 snapshotId) external returns (bool success); 1792 | | 1793 | | /// Revokes persistent status from the address, previously added via `makePersistent`. 1794 | | function revokePersistent(address account) external; 1795 | | 1796 | | /// See `revokePersistent(address)`. 1797 | | function revokePersistent(address[] calldata accounts) external; 1798 | | 1799 | | /// Sets `block.height`. 1800 | | function roll(uint256 newHeight) external; 1801 | | 1802 | | /// Updates the currently active fork to given block number 1803 | | /// This is similar to `roll` but for the currently active fork. 1804 | | function rollFork(uint256 blockNumber) external; 1805 | | 1806 | | /// Updates the currently active fork to given transaction. This will `rollFork` with the number 1807 | | /// of the block the transaction was mined in and replays all transaction mined before it in the block. 1808 | | function rollFork(bytes32 txHash) external; 1809 | | 1810 | | /// Updates the given fork to given block number. 1811 | | function rollFork(uint256 forkId, uint256 blockNumber) external; 1812 | | 1813 | | /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block. 1814 | | function rollFork(uint256 forkId, bytes32 txHash) external; 1815 | | 1816 | | /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. 1817 | | function selectFork(uint256 forkId) external; 1818 | | 1819 | | /// Set blockhash for the current block. 1820 | | /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`. 1821 | | function setBlockhash(uint256 blockNumber, bytes32 blockHash) external; 1822 | | 1823 | | /// Sets the nonce of an account. Must be higher than the current nonce of the account. 1824 | | function setNonce(address account, uint64 newNonce) external; 1825 | | 1826 | | /// Sets the nonce of an account to an arbitrary value. 1827 | | function setNonceUnsafe(address account, uint64 newNonce) external; 1828 | | 1829 | | /// Snapshot the current state of the evm. 1830 | | /// Returns the ID of the snapshot that was created. 1831 | | /// To revert a snapshot use `revertTo`. 1832 | | function snapshot() external returns (uint256 snapshotId); 1833 | | 1834 | | /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. 1835 | | function startPrank(address msgSender) external; 1836 | | 1837 | | /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. 1838 | | function startPrank(address msgSender, address txOrigin) external; 1839 | | 1840 | | /// Resets subsequent calls' `msg.sender` to be `address(this)`. 1841 | | function stopPrank() external; 1842 | | 1843 | | /// Stores a value to an address' storage slot. 1844 | | function store(address target, bytes32 slot, bytes32 value) external; 1845 | | 1846 | | /// Fetches the given transaction from the active fork and executes it on the current state. 1847 | | function transact(bytes32 txHash) external; 1848 | | 1849 | | /// Fetches the given transaction from the given fork and executes it on the current state. 1850 | | function transact(uint256 forkId, bytes32 txHash) external; 1851 | | 1852 | | /// Sets `tx.gasprice`. 1853 | | function txGasPrice(uint256 newGasPrice) external; 1854 | | 1855 | | /// Sets `block.timestamp`. 1856 | | function warp(uint256 newTimestamp) external; 1857 | | 1858 | | // ======== Testing ======== 1859 | | 1860 | | /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. 1861 | | function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; 1862 | | 1863 | | /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. 1864 | | function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) 1865 | | external; 1866 | | 1867 | | /// Expects a call to an address with the specified calldata. 1868 | | /// Calldata can either be a strict or a partial match. 1869 | | function expectCall(address callee, bytes calldata data) external; 1870 | | 1871 | | /// Expects given number of calls to an address with the specified calldata. 1872 | | function expectCall(address callee, bytes calldata data, uint64 count) external; 1873 | | 1874 | | /// Expects a call to an address with the specified `msg.value` and calldata. 1875 | | function expectCall(address callee, uint256 msgValue, bytes calldata data) external; 1876 | | 1877 | | /// Expects given number of calls to an address with the specified `msg.value` and calldata. 1878 | | function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external; 1879 | | 1880 | | /// Expect a call to an address with the specified `msg.value`, gas, and calldata. 1881 | | function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external; 1882 | | 1883 | | /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata. 1884 | | function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external; 1885 | | 1886 | | /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). 1887 | | /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if 1888 | | /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). 1889 | | function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) 1890 | | external; 1891 | | 1892 | | /// Same as the previous method, but also checks supplied address against emitting contract. 1893 | | function expectEmitAnonymous( 1894 | | bool checkTopic0, 1895 | | bool checkTopic1, 1896 | | bool checkTopic2, 1897 | | bool checkTopic3, 1898 | | bool checkData, 1899 | | address emitter 1900 | | ) external; 1901 | | 1902 | | /// Prepare an expected anonymous log with all topic and data checks enabled. 1903 | | /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if 1904 | | /// logs were emitted in the expected order with the expected topics and data. 1905 | | function expectEmitAnonymous() external; 1906 | | 1907 | | /// Same as the previous method, but also checks supplied address against emitting contract. 1908 | | function expectEmitAnonymous(address emitter) external; 1909 | | 1910 | | /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.). 1911 | | /// Call this function, then emit an event, then call a function. Internally after the call, we check if 1912 | | /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans). 1913 | | function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external; 1914 | | 1915 | | /// Same as the previous method, but also checks supplied address against emitting contract. 1916 | | function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter) 1917 | | external; 1918 | | 1919 | | /// Prepare an expected log with all topic and data checks enabled. 1920 | | /// Call this function, then emit an event, then call a function. Internally after the call, we check if 1921 | | /// logs were emitted in the expected order with the expected topics and data. 1922 | | function expectEmit() external; 1923 | | 1924 | | /// Same as the previous method, but also checks supplied address against emitting contract. 1925 | | function expectEmit(address emitter) external; 1926 | | 1927 | | /// Expects an error on next call that starts with the revert data. 1928 | | function expectPartialRevert(bytes4 revertData) external; 1929 | | 1930 | | /// Expects an error on next call to reverter address, that starts with the revert data. 1931 | | function expectPartialRevert(bytes4 revertData, address reverter) external; 1932 | | 1933 | | /// Expects an error on next call with any revert data. 1934 | | function expectRevert() external; 1935 | | 1936 | | /// Expects an error on next call that exactly matches the revert data. 1937 | | function expectRevert(bytes4 revertData) external; 1938 | | 1939 | | /// Expects an error on next call that exactly matches the revert data. 1940 | | function expectRevert(bytes calldata revertData) external; 1941 | | 1942 | | /// Expects an error with any revert data on next call to reverter address. 1943 | | function expectRevert(address reverter) external; 1944 | | 1945 | | /// Expects an error from reverter address on next call, with any revert data. 1946 | | function expectRevert(bytes4 revertData, address reverter) external; 1947 | | 1948 | | /// Expects an error from reverter address on next call, that exactly matches the revert data. 1949 | | function expectRevert(bytes calldata revertData, address reverter) external; 1950 | | 1951 | | /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other 1952 | | /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set. 1953 | | function expectSafeMemory(uint64 min, uint64 max) external; 1954 | | 1955 | | /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext. 1956 | | /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges 1957 | | /// to the set. 1958 | | function expectSafeMemoryCall(uint64 min, uint64 max) external; 1959 | | 1960 | | /// Marks a test as skipped. Must be called at the top level of a test. 1961 | | function skip(bool skipTest) external; 1962 | | 1963 | | /// Marks a test as skipped with a reason. Must be called at the top level of a test. 1964 | | function skip(bool skipTest, string calldata reason) external; 1965 | | 1966 | | /// Stops all safe memory expectation in the current subcontext. 1967 | | function stopExpectSafeMemory() external; 1968 | | } 1969 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/console.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.4.22 <0.9.0; 3 | | 4 | * | library console { 5 | | address constant CONSOLE_ADDRESS = 6 | | 0x000000000000000000636F6e736F6c652e6c6f67; 7 | | 8 | | function _sendLogPayloadImplementation(bytes memory payload) internal view { 9 | | address consoleAddress = CONSOLE_ADDRESS; 10 | | /// @solidity memory-safe-assembly 11 | | assembly { 12 | | pop( 13 | | staticcall( 14 | | gas(), 15 | | consoleAddress, 16 | | add(payload, 32), 17 | | mload(payload), 18 | | 0, 19 | | 0 20 | | ) 21 | | ) 22 | | } 23 | | } 24 | | 25 | | function _castToPure( 26 | | function(bytes memory) internal view fnIn 27 | | ) internal pure returns (function(bytes memory) pure fnOut) { 28 | | assembly { 29 | | fnOut := fnIn 30 | | } 31 | | } 32 | | 33 | | function _sendLogPayload(bytes memory payload) internal pure { 34 | | _castToPure(_sendLogPayloadImplementation)(payload); 35 | | } 36 | | 37 | | function log() internal pure { 38 | | _sendLogPayload(abi.encodeWithSignature("log()")); 39 | | } 40 | | 41 | | function logInt(int256 p0) internal pure { 42 | | _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); 43 | | } 44 | | 45 | | function logUint(uint256 p0) internal pure { 46 | | _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); 47 | | } 48 | | 49 | | function logString(string memory p0) internal pure { 50 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 51 | | } 52 | | 53 | | function logBool(bool p0) internal pure { 54 | | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 55 | | } 56 | | 57 | | function logAddress(address p0) internal pure { 58 | | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 59 | | } 60 | | 61 | | function logBytes(bytes memory p0) internal pure { 62 | | _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); 63 | | } 64 | | 65 | | function logBytes1(bytes1 p0) internal pure { 66 | | _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); 67 | | } 68 | | 69 | | function logBytes2(bytes2 p0) internal pure { 70 | | _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); 71 | | } 72 | | 73 | | function logBytes3(bytes3 p0) internal pure { 74 | | _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); 75 | | } 76 | | 77 | | function logBytes4(bytes4 p0) internal pure { 78 | | _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); 79 | | } 80 | | 81 | | function logBytes5(bytes5 p0) internal pure { 82 | | _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); 83 | | } 84 | | 85 | | function logBytes6(bytes6 p0) internal pure { 86 | | _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); 87 | | } 88 | | 89 | | function logBytes7(bytes7 p0) internal pure { 90 | | _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); 91 | | } 92 | | 93 | | function logBytes8(bytes8 p0) internal pure { 94 | | _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); 95 | | } 96 | | 97 | | function logBytes9(bytes9 p0) internal pure { 98 | | _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); 99 | | } 100 | | 101 | | function logBytes10(bytes10 p0) internal pure { 102 | | _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); 103 | | } 104 | | 105 | | function logBytes11(bytes11 p0) internal pure { 106 | | _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); 107 | | } 108 | | 109 | | function logBytes12(bytes12 p0) internal pure { 110 | | _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); 111 | | } 112 | | 113 | | function logBytes13(bytes13 p0) internal pure { 114 | | _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); 115 | | } 116 | | 117 | | function logBytes14(bytes14 p0) internal pure { 118 | | _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); 119 | | } 120 | | 121 | | function logBytes15(bytes15 p0) internal pure { 122 | | _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); 123 | | } 124 | | 125 | | function logBytes16(bytes16 p0) internal pure { 126 | | _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); 127 | | } 128 | | 129 | | function logBytes17(bytes17 p0) internal pure { 130 | | _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); 131 | | } 132 | | 133 | | function logBytes18(bytes18 p0) internal pure { 134 | | _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); 135 | | } 136 | | 137 | | function logBytes19(bytes19 p0) internal pure { 138 | | _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); 139 | | } 140 | | 141 | | function logBytes20(bytes20 p0) internal pure { 142 | | _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); 143 | | } 144 | | 145 | | function logBytes21(bytes21 p0) internal pure { 146 | | _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); 147 | | } 148 | | 149 | | function logBytes22(bytes22 p0) internal pure { 150 | | _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); 151 | | } 152 | | 153 | | function logBytes23(bytes23 p0) internal pure { 154 | | _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); 155 | | } 156 | | 157 | | function logBytes24(bytes24 p0) internal pure { 158 | | _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); 159 | | } 160 | | 161 | | function logBytes25(bytes25 p0) internal pure { 162 | | _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); 163 | | } 164 | | 165 | | function logBytes26(bytes26 p0) internal pure { 166 | | _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); 167 | | } 168 | | 169 | | function logBytes27(bytes27 p0) internal pure { 170 | | _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); 171 | | } 172 | | 173 | | function logBytes28(bytes28 p0) internal pure { 174 | | _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); 175 | | } 176 | | 177 | | function logBytes29(bytes29 p0) internal pure { 178 | | _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); 179 | | } 180 | | 181 | | function logBytes30(bytes30 p0) internal pure { 182 | | _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); 183 | | } 184 | | 185 | | function logBytes31(bytes31 p0) internal pure { 186 | | _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); 187 | | } 188 | | 189 | | function logBytes32(bytes32 p0) internal pure { 190 | | _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); 191 | | } 192 | | 193 | | function log(uint256 p0) internal pure { 194 | | _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); 195 | | } 196 | | 197 | | function log(int256 p0) internal pure { 198 | | _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); 199 | | } 200 | | 201 | | function log(string memory p0) internal pure { 202 | | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 203 | | } 204 | | 205 | | function log(bool p0) internal pure { 206 | | _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); 207 | | } 208 | | 209 | | function log(address p0) internal pure { 210 | | _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); 211 | | } 212 | | 213 | | function log(uint256 p0, uint256 p1) internal pure { 214 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); 215 | | } 216 | | 217 | | function log(uint256 p0, string memory p1) internal pure { 218 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); 219 | | } 220 | | 221 | | function log(uint256 p0, bool p1) internal pure { 222 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); 223 | | } 224 | | 225 | | function log(uint256 p0, address p1) internal pure { 226 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); 227 | | } 228 | | 229 | | function log(string memory p0, uint256 p1) internal pure { 230 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); 231 | | } 232 | | 233 | | function log(string memory p0, int256 p1) internal pure { 234 | | _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); 235 | | } 236 | | 237 | | function log(string memory p0, string memory p1) internal pure { 238 | | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 239 | | } 240 | | 241 | | function log(string memory p0, bool p1) internal pure { 242 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); 243 | | } 244 | | 245 | | function log(string memory p0, address p1) internal pure { 246 | | _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); 247 | | } 248 | | 249 | | function log(bool p0, uint256 p1) internal pure { 250 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); 251 | | } 252 | | 253 | | function log(bool p0, string memory p1) internal pure { 254 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); 255 | | } 256 | | 257 | | function log(bool p0, bool p1) internal pure { 258 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); 259 | | } 260 | | 261 | | function log(bool p0, address p1) internal pure { 262 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); 263 | | } 264 | | 265 | | function log(address p0, uint256 p1) internal pure { 266 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); 267 | | } 268 | | 269 | | function log(address p0, string memory p1) internal pure { 270 | | _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); 271 | | } 272 | | 273 | | function log(address p0, bool p1) internal pure { 274 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); 275 | | } 276 | | 277 | | function log(address p0, address p1) internal pure { 278 | | _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); 279 | | } 280 | | 281 | | function log(uint256 p0, uint256 p1, uint256 p2) internal pure { 282 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); 283 | | } 284 | | 285 | | function log(uint256 p0, uint256 p1, string memory p2) internal pure { 286 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); 287 | | } 288 | | 289 | | function log(uint256 p0, uint256 p1, bool p2) internal pure { 290 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); 291 | | } 292 | | 293 | | function log(uint256 p0, uint256 p1, address p2) internal pure { 294 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); 295 | | } 296 | | 297 | | function log(uint256 p0, string memory p1, uint256 p2) internal pure { 298 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); 299 | | } 300 | | 301 | | function log(uint256 p0, string memory p1, string memory p2) internal pure { 302 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); 303 | | } 304 | | 305 | | function log(uint256 p0, string memory p1, bool p2) internal pure { 306 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); 307 | | } 308 | | 309 | | function log(uint256 p0, string memory p1, address p2) internal pure { 310 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); 311 | | } 312 | | 313 | | function log(uint256 p0, bool p1, uint256 p2) internal pure { 314 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); 315 | | } 316 | | 317 | | function log(uint256 p0, bool p1, string memory p2) internal pure { 318 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); 319 | | } 320 | | 321 | | function log(uint256 p0, bool p1, bool p2) internal pure { 322 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); 323 | | } 324 | | 325 | | function log(uint256 p0, bool p1, address p2) internal pure { 326 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); 327 | | } 328 | | 329 | | function log(uint256 p0, address p1, uint256 p2) internal pure { 330 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); 331 | | } 332 | | 333 | | function log(uint256 p0, address p1, string memory p2) internal pure { 334 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); 335 | | } 336 | | 337 | | function log(uint256 p0, address p1, bool p2) internal pure { 338 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); 339 | | } 340 | | 341 | | function log(uint256 p0, address p1, address p2) internal pure { 342 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); 343 | | } 344 | | 345 | | function log(string memory p0, uint256 p1, uint256 p2) internal pure { 346 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); 347 | | } 348 | | 349 | | function log(string memory p0, uint256 p1, string memory p2) internal pure { 350 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); 351 | | } 352 | | 353 | | function log(string memory p0, uint256 p1, bool p2) internal pure { 354 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); 355 | | } 356 | | 357 | | function log(string memory p0, uint256 p1, address p2) internal pure { 358 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); 359 | | } 360 | | 361 | | function log(string memory p0, string memory p1, uint256 p2) internal pure { 362 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); 363 | | } 364 | | 365 | | function log(string memory p0, string memory p1, string memory p2) internal pure { 366 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); 367 | | } 368 | | 369 | | function log(string memory p0, string memory p1, bool p2) internal pure { 370 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); 371 | | } 372 | | 373 | | function log(string memory p0, string memory p1, address p2) internal pure { 374 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); 375 | | } 376 | | 377 | | function log(string memory p0, bool p1, uint256 p2) internal pure { 378 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); 379 | | } 380 | | 381 | | function log(string memory p0, bool p1, string memory p2) internal pure { 382 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); 383 | | } 384 | | 385 | | function log(string memory p0, bool p1, bool p2) internal pure { 386 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); 387 | | } 388 | | 389 | | function log(string memory p0, bool p1, address p2) internal pure { 390 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); 391 | | } 392 | | 393 | | function log(string memory p0, address p1, uint256 p2) internal pure { 394 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); 395 | | } 396 | | 397 | | function log(string memory p0, address p1, string memory p2) internal pure { 398 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); 399 | | } 400 | | 401 | | function log(string memory p0, address p1, bool p2) internal pure { 402 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); 403 | | } 404 | | 405 | | function log(string memory p0, address p1, address p2) internal pure { 406 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); 407 | | } 408 | | 409 | | function log(bool p0, uint256 p1, uint256 p2) internal pure { 410 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); 411 | | } 412 | | 413 | | function log(bool p0, uint256 p1, string memory p2) internal pure { 414 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); 415 | | } 416 | | 417 | | function log(bool p0, uint256 p1, bool p2) internal pure { 418 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); 419 | | } 420 | | 421 | | function log(bool p0, uint256 p1, address p2) internal pure { 422 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); 423 | | } 424 | | 425 | | function log(bool p0, string memory p1, uint256 p2) internal pure { 426 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); 427 | | } 428 | | 429 | | function log(bool p0, string memory p1, string memory p2) internal pure { 430 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); 431 | | } 432 | | 433 | | function log(bool p0, string memory p1, bool p2) internal pure { 434 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); 435 | | } 436 | | 437 | | function log(bool p0, string memory p1, address p2) internal pure { 438 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); 439 | | } 440 | | 441 | | function log(bool p0, bool p1, uint256 p2) internal pure { 442 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); 443 | | } 444 | | 445 | | function log(bool p0, bool p1, string memory p2) internal pure { 446 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); 447 | | } 448 | | 449 | | function log(bool p0, bool p1, bool p2) internal pure { 450 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); 451 | | } 452 | | 453 | | function log(bool p0, bool p1, address p2) internal pure { 454 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); 455 | | } 456 | | 457 | | function log(bool p0, address p1, uint256 p2) internal pure { 458 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); 459 | | } 460 | | 461 | | function log(bool p0, address p1, string memory p2) internal pure { 462 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); 463 | | } 464 | | 465 | | function log(bool p0, address p1, bool p2) internal pure { 466 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); 467 | | } 468 | | 469 | | function log(bool p0, address p1, address p2) internal pure { 470 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); 471 | | } 472 | | 473 | | function log(address p0, uint256 p1, uint256 p2) internal pure { 474 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); 475 | | } 476 | | 477 | | function log(address p0, uint256 p1, string memory p2) internal pure { 478 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); 479 | | } 480 | | 481 | | function log(address p0, uint256 p1, bool p2) internal pure { 482 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); 483 | | } 484 | | 485 | | function log(address p0, uint256 p1, address p2) internal pure { 486 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); 487 | | } 488 | | 489 | | function log(address p0, string memory p1, uint256 p2) internal pure { 490 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); 491 | | } 492 | | 493 | | function log(address p0, string memory p1, string memory p2) internal pure { 494 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); 495 | | } 496 | | 497 | | function log(address p0, string memory p1, bool p2) internal pure { 498 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); 499 | | } 500 | | 501 | | function log(address p0, string memory p1, address p2) internal pure { 502 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); 503 | | } 504 | | 505 | | function log(address p0, bool p1, uint256 p2) internal pure { 506 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); 507 | | } 508 | | 509 | | function log(address p0, bool p1, string memory p2) internal pure { 510 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); 511 | | } 512 | | 513 | | function log(address p0, bool p1, bool p2) internal pure { 514 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); 515 | | } 516 | | 517 | | function log(address p0, bool p1, address p2) internal pure { 518 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); 519 | | } 520 | | 521 | | function log(address p0, address p1, uint256 p2) internal pure { 522 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); 523 | | } 524 | | 525 | | function log(address p0, address p1, string memory p2) internal pure { 526 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); 527 | | } 528 | | 529 | | function log(address p0, address p1, bool p2) internal pure { 530 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); 531 | | } 532 | | 533 | | function log(address p0, address p1, address p2) internal pure { 534 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); 535 | | } 536 | | 537 | | function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 538 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); 539 | | } 540 | | 541 | | function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { 542 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); 543 | | } 544 | | 545 | | function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { 546 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); 547 | | } 548 | | 549 | | function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { 550 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); 551 | | } 552 | | 553 | | function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { 554 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); 555 | | } 556 | | 557 | | function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { 558 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); 559 | | } 560 | | 561 | | function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { 562 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); 563 | | } 564 | | 565 | | function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { 566 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); 567 | | } 568 | | 569 | | function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { 570 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); 571 | | } 572 | | 573 | | function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { 574 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); 575 | | } 576 | | 577 | | function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { 578 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); 579 | | } 580 | | 581 | | function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { 582 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); 583 | | } 584 | | 585 | | function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { 586 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); 587 | | } 588 | | 589 | | function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { 590 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); 591 | | } 592 | | 593 | | function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { 594 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); 595 | | } 596 | | 597 | | function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { 598 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); 599 | | } 600 | | 601 | | function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { 602 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); 603 | | } 604 | | 605 | | function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { 606 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); 607 | | } 608 | | 609 | | function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { 610 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); 611 | | } 612 | | 613 | | function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { 614 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); 615 | | } 616 | | 617 | | function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { 618 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); 619 | | } 620 | | 621 | | function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { 622 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); 623 | | } 624 | | 625 | | function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { 626 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); 627 | | } 628 | | 629 | | function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { 630 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); 631 | | } 632 | | 633 | | function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { 634 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); 635 | | } 636 | | 637 | | function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { 638 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); 639 | | } 640 | | 641 | | function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { 642 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); 643 | | } 644 | | 645 | | function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { 646 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); 647 | | } 648 | | 649 | | function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { 650 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); 651 | | } 652 | | 653 | | function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { 654 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); 655 | | } 656 | | 657 | | function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { 658 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); 659 | | } 660 | | 661 | | function log(uint256 p0, string memory p1, address p2, address p3) internal pure { 662 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); 663 | | } 664 | | 665 | | function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { 666 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); 667 | | } 668 | | 669 | | function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { 670 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); 671 | | } 672 | | 673 | | function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { 674 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); 675 | | } 676 | | 677 | | function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { 678 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); 679 | | } 680 | | 681 | | function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { 682 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); 683 | | } 684 | | 685 | | function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { 686 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); 687 | | } 688 | | 689 | | function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { 690 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); 691 | | } 692 | | 693 | | function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { 694 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); 695 | | } 696 | | 697 | | function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { 698 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); 699 | | } 700 | | 701 | | function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { 702 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); 703 | | } 704 | | 705 | | function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { 706 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); 707 | | } 708 | | 709 | | function log(uint256 p0, bool p1, bool p2, address p3) internal pure { 710 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); 711 | | } 712 | | 713 | | function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { 714 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); 715 | | } 716 | | 717 | | function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { 718 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); 719 | | } 720 | | 721 | | function log(uint256 p0, bool p1, address p2, bool p3) internal pure { 722 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); 723 | | } 724 | | 725 | | function log(uint256 p0, bool p1, address p2, address p3) internal pure { 726 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); 727 | | } 728 | | 729 | | function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { 730 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); 731 | | } 732 | | 733 | | function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { 734 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); 735 | | } 736 | | 737 | | function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { 738 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); 739 | | } 740 | | 741 | | function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { 742 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); 743 | | } 744 | | 745 | | function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { 746 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); 747 | | } 748 | | 749 | | function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { 750 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); 751 | | } 752 | | 753 | | function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { 754 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); 755 | | } 756 | | 757 | | function log(uint256 p0, address p1, string memory p2, address p3) internal pure { 758 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); 759 | | } 760 | | 761 | | function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { 762 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); 763 | | } 764 | | 765 | | function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { 766 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); 767 | | } 768 | | 769 | | function log(uint256 p0, address p1, bool p2, bool p3) internal pure { 770 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); 771 | | } 772 | | 773 | | function log(uint256 p0, address p1, bool p2, address p3) internal pure { 774 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); 775 | | } 776 | | 777 | | function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { 778 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); 779 | | } 780 | | 781 | | function log(uint256 p0, address p1, address p2, string memory p3) internal pure { 782 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); 783 | | } 784 | | 785 | | function log(uint256 p0, address p1, address p2, bool p3) internal pure { 786 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); 787 | | } 788 | | 789 | | function log(uint256 p0, address p1, address p2, address p3) internal pure { 790 | | _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); 791 | | } 792 | | 793 | | function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 794 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); 795 | | } 796 | | 797 | | function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { 798 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); 799 | | } 800 | | 801 | | function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { 802 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); 803 | | } 804 | | 805 | | function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { 806 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); 807 | | } 808 | | 809 | | function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { 810 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); 811 | | } 812 | | 813 | | function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { 814 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); 815 | | } 816 | | 817 | | function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { 818 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); 819 | | } 820 | | 821 | | function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { 822 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); 823 | | } 824 | | 825 | | function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { 826 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); 827 | | } 828 | | 829 | | function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { 830 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); 831 | | } 832 | | 833 | | function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { 834 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); 835 | | } 836 | | 837 | | function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { 838 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); 839 | | } 840 | | 841 | | function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { 842 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); 843 | | } 844 | | 845 | | function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { 846 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); 847 | | } 848 | | 849 | | function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { 850 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); 851 | | } 852 | | 853 | | function log(string memory p0, uint256 p1, address p2, address p3) internal pure { 854 | | _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); 855 | | } 856 | | 857 | | function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { 858 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); 859 | | } 860 | | 861 | | function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { 862 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); 863 | | } 864 | | 865 | | function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { 866 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); 867 | | } 868 | | 869 | | function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { 870 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); 871 | | } 872 | | 873 | | function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { 874 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); 875 | | } 876 | | 877 | | function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { 878 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); 879 | | } 880 | | 881 | | function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { 882 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); 883 | | } 884 | | 885 | | function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { 886 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); 887 | | } 888 | | 889 | | function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { 890 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); 891 | | } 892 | | 893 | | function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { 894 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); 895 | | } 896 | | 897 | | function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { 898 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); 899 | | } 900 | | 901 | | function log(string memory p0, string memory p1, bool p2, address p3) internal pure { 902 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); 903 | | } 904 | | 905 | | function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { 906 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); 907 | | } 908 | | 909 | | function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { 910 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); 911 | | } 912 | | 913 | | function log(string memory p0, string memory p1, address p2, bool p3) internal pure { 914 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); 915 | | } 916 | | 917 | | function log(string memory p0, string memory p1, address p2, address p3) internal pure { 918 | | _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); 919 | | } 920 | | 921 | | function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { 922 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); 923 | | } 924 | | 925 | | function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { 926 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); 927 | | } 928 | | 929 | | function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { 930 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); 931 | | } 932 | | 933 | | function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { 934 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); 935 | | } 936 | | 937 | | function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { 938 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); 939 | | } 940 | | 941 | | function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { 942 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); 943 | | } 944 | | 945 | | function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { 946 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); 947 | | } 948 | | 949 | | function log(string memory p0, bool p1, string memory p2, address p3) internal pure { 950 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); 951 | | } 952 | | 953 | | function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { 954 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); 955 | | } 956 | | 957 | | function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { 958 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); 959 | | } 960 | | 961 | | function log(string memory p0, bool p1, bool p2, bool p3) internal pure { 962 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); 963 | | } 964 | | 965 | | function log(string memory p0, bool p1, bool p2, address p3) internal pure { 966 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); 967 | | } 968 | | 969 | | function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { 970 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); 971 | | } 972 | | 973 | | function log(string memory p0, bool p1, address p2, string memory p3) internal pure { 974 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); 975 | | } 976 | | 977 | | function log(string memory p0, bool p1, address p2, bool p3) internal pure { 978 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); 979 | | } 980 | | 981 | | function log(string memory p0, bool p1, address p2, address p3) internal pure { 982 | | _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); 983 | | } 984 | | 985 | | function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { 986 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); 987 | | } 988 | | 989 | | function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { 990 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); 991 | | } 992 | | 993 | | function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { 994 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); 995 | | } 996 | | 997 | | function log(string memory p0, address p1, uint256 p2, address p3) internal pure { 998 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); 999 | | } 1000 | | 1001 | | function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { 1002 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); 1003 | | } 1004 | | 1005 | | function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { 1006 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); 1007 | | } 1008 | | 1009 | | function log(string memory p0, address p1, string memory p2, bool p3) internal pure { 1010 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); 1011 | | } 1012 | | 1013 | | function log(string memory p0, address p1, string memory p2, address p3) internal pure { 1014 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); 1015 | | } 1016 | | 1017 | | function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { 1018 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); 1019 | | } 1020 | | 1021 | | function log(string memory p0, address p1, bool p2, string memory p3) internal pure { 1022 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); 1023 | | } 1024 | | 1025 | | function log(string memory p0, address p1, bool p2, bool p3) internal pure { 1026 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); 1027 | | } 1028 | | 1029 | | function log(string memory p0, address p1, bool p2, address p3) internal pure { 1030 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); 1031 | | } 1032 | | 1033 | | function log(string memory p0, address p1, address p2, uint256 p3) internal pure { 1034 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); 1035 | | } 1036 | | 1037 | | function log(string memory p0, address p1, address p2, string memory p3) internal pure { 1038 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); 1039 | | } 1040 | | 1041 | | function log(string memory p0, address p1, address p2, bool p3) internal pure { 1042 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); 1043 | | } 1044 | | 1045 | | function log(string memory p0, address p1, address p2, address p3) internal pure { 1046 | | _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); 1047 | | } 1048 | | 1049 | | function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 1050 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); 1051 | | } 1052 | | 1053 | | function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { 1054 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); 1055 | | } 1056 | | 1057 | | function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { 1058 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); 1059 | | } 1060 | | 1061 | | function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { 1062 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); 1063 | | } 1064 | | 1065 | | function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { 1066 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); 1067 | | } 1068 | | 1069 | | function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { 1070 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); 1071 | | } 1072 | | 1073 | | function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { 1074 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); 1075 | | } 1076 | | 1077 | | function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { 1078 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); 1079 | | } 1080 | | 1081 | | function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { 1082 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); 1083 | | } 1084 | | 1085 | | function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { 1086 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); 1087 | | } 1088 | | 1089 | | function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { 1090 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); 1091 | | } 1092 | | 1093 | | function log(bool p0, uint256 p1, bool p2, address p3) internal pure { 1094 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); 1095 | | } 1096 | | 1097 | | function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { 1098 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); 1099 | | } 1100 | | 1101 | | function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { 1102 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); 1103 | | } 1104 | | 1105 | | function log(bool p0, uint256 p1, address p2, bool p3) internal pure { 1106 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); 1107 | | } 1108 | | 1109 | | function log(bool p0, uint256 p1, address p2, address p3) internal pure { 1110 | | _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); 1111 | | } 1112 | | 1113 | | function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { 1114 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); 1115 | | } 1116 | | 1117 | | function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { 1118 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); 1119 | | } 1120 | | 1121 | | function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { 1122 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); 1123 | | } 1124 | | 1125 | | function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { 1126 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); 1127 | | } 1128 | | 1129 | | function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { 1130 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); 1131 | | } 1132 | | 1133 | | function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { 1134 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); 1135 | | } 1136 | | 1137 | | function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { 1138 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); 1139 | | } 1140 | | 1141 | | function log(bool p0, string memory p1, string memory p2, address p3) internal pure { 1142 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); 1143 | | } 1144 | | 1145 | | function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { 1146 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); 1147 | | } 1148 | | 1149 | | function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { 1150 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); 1151 | | } 1152 | | 1153 | | function log(bool p0, string memory p1, bool p2, bool p3) internal pure { 1154 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); 1155 | | } 1156 | | 1157 | | function log(bool p0, string memory p1, bool p2, address p3) internal pure { 1158 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); 1159 | | } 1160 | | 1161 | | function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { 1162 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); 1163 | | } 1164 | | 1165 | | function log(bool p0, string memory p1, address p2, string memory p3) internal pure { 1166 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); 1167 | | } 1168 | | 1169 | | function log(bool p0, string memory p1, address p2, bool p3) internal pure { 1170 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); 1171 | | } 1172 | | 1173 | | function log(bool p0, string memory p1, address p2, address p3) internal pure { 1174 | | _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); 1175 | | } 1176 | | 1177 | | function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { 1178 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); 1179 | | } 1180 | | 1181 | | function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { 1182 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); 1183 | | } 1184 | | 1185 | | function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { 1186 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); 1187 | | } 1188 | | 1189 | | function log(bool p0, bool p1, uint256 p2, address p3) internal pure { 1190 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); 1191 | | } 1192 | | 1193 | | function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { 1194 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); 1195 | | } 1196 | | 1197 | | function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { 1198 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); 1199 | | } 1200 | | 1201 | | function log(bool p0, bool p1, string memory p2, bool p3) internal pure { 1202 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); 1203 | | } 1204 | | 1205 | | function log(bool p0, bool p1, string memory p2, address p3) internal pure { 1206 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); 1207 | | } 1208 | | 1209 | | function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { 1210 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); 1211 | | } 1212 | | 1213 | | function log(bool p0, bool p1, bool p2, string memory p3) internal pure { 1214 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); 1215 | | } 1216 | | 1217 | | function log(bool p0, bool p1, bool p2, bool p3) internal pure { 1218 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); 1219 | | } 1220 | | 1221 | | function log(bool p0, bool p1, bool p2, address p3) internal pure { 1222 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); 1223 | | } 1224 | | 1225 | | function log(bool p0, bool p1, address p2, uint256 p3) internal pure { 1226 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); 1227 | | } 1228 | | 1229 | | function log(bool p0, bool p1, address p2, string memory p3) internal pure { 1230 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); 1231 | | } 1232 | | 1233 | | function log(bool p0, bool p1, address p2, bool p3) internal pure { 1234 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); 1235 | | } 1236 | | 1237 | | function log(bool p0, bool p1, address p2, address p3) internal pure { 1238 | | _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); 1239 | | } 1240 | | 1241 | | function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { 1242 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); 1243 | | } 1244 | | 1245 | | function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { 1246 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); 1247 | | } 1248 | | 1249 | | function log(bool p0, address p1, uint256 p2, bool p3) internal pure { 1250 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); 1251 | | } 1252 | | 1253 | | function log(bool p0, address p1, uint256 p2, address p3) internal pure { 1254 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); 1255 | | } 1256 | | 1257 | | function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { 1258 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); 1259 | | } 1260 | | 1261 | | function log(bool p0, address p1, string memory p2, string memory p3) internal pure { 1262 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); 1263 | | } 1264 | | 1265 | | function log(bool p0, address p1, string memory p2, bool p3) internal pure { 1266 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); 1267 | | } 1268 | | 1269 | | function log(bool p0, address p1, string memory p2, address p3) internal pure { 1270 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); 1271 | | } 1272 | | 1273 | | function log(bool p0, address p1, bool p2, uint256 p3) internal pure { 1274 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); 1275 | | } 1276 | | 1277 | | function log(bool p0, address p1, bool p2, string memory p3) internal pure { 1278 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); 1279 | | } 1280 | | 1281 | | function log(bool p0, address p1, bool p2, bool p3) internal pure { 1282 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); 1283 | | } 1284 | | 1285 | | function log(bool p0, address p1, bool p2, address p3) internal pure { 1286 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); 1287 | | } 1288 | | 1289 | | function log(bool p0, address p1, address p2, uint256 p3) internal pure { 1290 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); 1291 | | } 1292 | | 1293 | | function log(bool p0, address p1, address p2, string memory p3) internal pure { 1294 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); 1295 | | } 1296 | | 1297 | | function log(bool p0, address p1, address p2, bool p3) internal pure { 1298 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); 1299 | | } 1300 | | 1301 | | function log(bool p0, address p1, address p2, address p3) internal pure { 1302 | | _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); 1303 | | } 1304 | | 1305 | | function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 1306 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); 1307 | | } 1308 | | 1309 | | function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { 1310 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); 1311 | | } 1312 | | 1313 | | function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { 1314 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); 1315 | | } 1316 | | 1317 | | function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { 1318 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); 1319 | | } 1320 | | 1321 | | function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { 1322 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); 1323 | | } 1324 | | 1325 | | function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { 1326 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); 1327 | | } 1328 | | 1329 | | function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { 1330 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); 1331 | | } 1332 | | 1333 | | function log(address p0, uint256 p1, string memory p2, address p3) internal pure { 1334 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); 1335 | | } 1336 | | 1337 | | function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { 1338 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); 1339 | | } 1340 | | 1341 | | function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { 1342 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); 1343 | | } 1344 | | 1345 | | function log(address p0, uint256 p1, bool p2, bool p3) internal pure { 1346 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); 1347 | | } 1348 | | 1349 | | function log(address p0, uint256 p1, bool p2, address p3) internal pure { 1350 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); 1351 | | } 1352 | | 1353 | | function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { 1354 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); 1355 | | } 1356 | | 1357 | | function log(address p0, uint256 p1, address p2, string memory p3) internal pure { 1358 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); 1359 | | } 1360 | | 1361 | | function log(address p0, uint256 p1, address p2, bool p3) internal pure { 1362 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); 1363 | | } 1364 | | 1365 | | function log(address p0, uint256 p1, address p2, address p3) internal pure { 1366 | | _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); 1367 | | } 1368 | | 1369 | | function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { 1370 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); 1371 | | } 1372 | | 1373 | | function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { 1374 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); 1375 | | } 1376 | | 1377 | | function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { 1378 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); 1379 | | } 1380 | | 1381 | | function log(address p0, string memory p1, uint256 p2, address p3) internal pure { 1382 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); 1383 | | } 1384 | | 1385 | | function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { 1386 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); 1387 | | } 1388 | | 1389 | | function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { 1390 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); 1391 | | } 1392 | | 1393 | | function log(address p0, string memory p1, string memory p2, bool p3) internal pure { 1394 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); 1395 | | } 1396 | | 1397 | | function log(address p0, string memory p1, string memory p2, address p3) internal pure { 1398 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); 1399 | | } 1400 | | 1401 | | function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { 1402 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); 1403 | | } 1404 | | 1405 | | function log(address p0, string memory p1, bool p2, string memory p3) internal pure { 1406 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); 1407 | | } 1408 | | 1409 | | function log(address p0, string memory p1, bool p2, bool p3) internal pure { 1410 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); 1411 | | } 1412 | | 1413 | | function log(address p0, string memory p1, bool p2, address p3) internal pure { 1414 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); 1415 | | } 1416 | | 1417 | | function log(address p0, string memory p1, address p2, uint256 p3) internal pure { 1418 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); 1419 | | } 1420 | | 1421 | | function log(address p0, string memory p1, address p2, string memory p3) internal pure { 1422 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); 1423 | | } 1424 | | 1425 | | function log(address p0, string memory p1, address p2, bool p3) internal pure { 1426 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); 1427 | | } 1428 | | 1429 | | function log(address p0, string memory p1, address p2, address p3) internal pure { 1430 | | _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); 1431 | | } 1432 | | 1433 | | function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { 1434 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); 1435 | | } 1436 | | 1437 | | function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { 1438 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); 1439 | | } 1440 | | 1441 | | function log(address p0, bool p1, uint256 p2, bool p3) internal pure { 1442 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); 1443 | | } 1444 | | 1445 | | function log(address p0, bool p1, uint256 p2, address p3) internal pure { 1446 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); 1447 | | } 1448 | | 1449 | | function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { 1450 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); 1451 | | } 1452 | | 1453 | | function log(address p0, bool p1, string memory p2, string memory p3) internal pure { 1454 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); 1455 | | } 1456 | | 1457 | | function log(address p0, bool p1, string memory p2, bool p3) internal pure { 1458 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); 1459 | | } 1460 | | 1461 | | function log(address p0, bool p1, string memory p2, address p3) internal pure { 1462 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); 1463 | | } 1464 | | 1465 | | function log(address p0, bool p1, bool p2, uint256 p3) internal pure { 1466 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); 1467 | | } 1468 | | 1469 | | function log(address p0, bool p1, bool p2, string memory p3) internal pure { 1470 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); 1471 | | } 1472 | | 1473 | | function log(address p0, bool p1, bool p2, bool p3) internal pure { 1474 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); 1475 | | } 1476 | | 1477 | | function log(address p0, bool p1, bool p2, address p3) internal pure { 1478 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); 1479 | | } 1480 | | 1481 | | function log(address p0, bool p1, address p2, uint256 p3) internal pure { 1482 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); 1483 | | } 1484 | | 1485 | | function log(address p0, bool p1, address p2, string memory p3) internal pure { 1486 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); 1487 | | } 1488 | | 1489 | | function log(address p0, bool p1, address p2, bool p3) internal pure { 1490 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); 1491 | | } 1492 | | 1493 | | function log(address p0, bool p1, address p2, address p3) internal pure { 1494 | | _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); 1495 | | } 1496 | | 1497 | | function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { 1498 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); 1499 | | } 1500 | | 1501 | | function log(address p0, address p1, uint256 p2, string memory p3) internal pure { 1502 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); 1503 | | } 1504 | | 1505 | | function log(address p0, address p1, uint256 p2, bool p3) internal pure { 1506 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); 1507 | | } 1508 | | 1509 | | function log(address p0, address p1, uint256 p2, address p3) internal pure { 1510 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); 1511 | | } 1512 | | 1513 | | function log(address p0, address p1, string memory p2, uint256 p3) internal pure { 1514 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); 1515 | | } 1516 | | 1517 | | function log(address p0, address p1, string memory p2, string memory p3) internal pure { 1518 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); 1519 | | } 1520 | | 1521 | | function log(address p0, address p1, string memory p2, bool p3) internal pure { 1522 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); 1523 | | } 1524 | | 1525 | | function log(address p0, address p1, string memory p2, address p3) internal pure { 1526 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); 1527 | | } 1528 | | 1529 | | function log(address p0, address p1, bool p2, uint256 p3) internal pure { 1530 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); 1531 | | } 1532 | | 1533 | | function log(address p0, address p1, bool p2, string memory p3) internal pure { 1534 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); 1535 | | } 1536 | | 1537 | | function log(address p0, address p1, bool p2, bool p3) internal pure { 1538 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); 1539 | | } 1540 | | 1541 | | function log(address p0, address p1, bool p2, address p3) internal pure { 1542 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); 1543 | | } 1544 | | 1545 | | function log(address p0, address p1, address p2, uint256 p3) internal pure { 1546 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); 1547 | | } 1548 | | 1549 | | function log(address p0, address p1, address p2, string memory p3) internal pure { 1550 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); 1551 | | } 1552 | | 1553 | | function log(address p0, address p1, address p2, bool p3) internal pure { 1554 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); 1555 | | } 1556 | | 1557 | | function log(address p0, address p1, address p2, address p3) internal pure { 1558 | | _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); 1559 | | } 1560 | | } 1561 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/console2.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.4.22 <0.9.0; 3 | | 4 | | import {console as console2} from "./console.sol"; 5 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC165.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2; 3 | | 4 | | interface IERC165 { 5 | | /// @notice Query if a contract implements an interface 6 | | /// @param interfaceID The interface identifier, as specified in ERC-165 7 | | /// @dev Interface identification is specified in ERC-165. This function 8 | | /// uses less than 30,000 gas. 9 | | /// @return `true` if the contract implements `interfaceID` and 10 | | /// `interfaceID` is not 0xffffffff, `false` otherwise 11 | | function supportsInterface(bytes4 interfaceID) external view returns (bool); 12 | | } 13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC20.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2; 3 | | 4 | | /// @dev Interface of the ERC20 standard as defined in the EIP. 5 | | /// @dev This includes the optional name, symbol, and decimals metadata. 6 | | interface IERC20 { 7 | | /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). 8 | | event Transfer(address indexed from, address indexed to, uint256 value); 9 | | 10 | | /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` 11 | | /// is the new allowance. 12 | | event Approval(address indexed owner, address indexed spender, uint256 value); 13 | | 14 | | /// @notice Returns the amount of tokens in existence. 15 | | function totalSupply() external view returns (uint256); 16 | | 17 | | /// @notice Returns the amount of tokens owned by `account`. 18 | | function balanceOf(address account) external view returns (uint256); 19 | | 20 | | /// @notice Moves `amount` tokens from the caller's account to `to`. 21 | | function transfer(address to, uint256 amount) external returns (bool); 22 | | 23 | | /// @notice Returns the remaining number of tokens that `spender` is allowed 24 | | /// to spend on behalf of `owner` 25 | | function allowance(address owner, address spender) external view returns (uint256); 26 | | 27 | | /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. 28 | | /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 29 | | function approve(address spender, uint256 amount) external returns (bool); 30 | | 31 | | /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. 32 | | /// `amount` is then deducted from the caller's allowance. 33 | | function transferFrom(address from, address to, uint256 amount) external returns (bool); 34 | | 35 | | /// @notice Returns the name of the token. 36 | | function name() external view returns (string memory); 37 | | 38 | | /// @notice Returns the symbol of the token. 39 | | function symbol() external view returns (string memory); 40 | | 41 | | /// @notice Returns the decimals places of the token. 42 | | function decimals() external view returns (uint8); 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IERC721.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2; 3 | | 4 | | import "./IERC165.sol"; 5 | | 6 | | /// @title ERC-721 Non-Fungible Token Standard 7 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721 8 | | /// Note: the ERC-165 identifier for this interface is 0x80ac58cd. 9 | | interface IERC721 is IERC165 { 10 | | /// @dev This emits when ownership of any NFT changes by any mechanism. 11 | | /// This event emits when NFTs are created (`from` == 0) and destroyed 12 | | /// (`to` == 0). Exception: during contract creation, any number of NFTs 13 | | /// may be created and assigned without emitting Transfer. At the time of 14 | | /// any transfer, the approved address for that NFT (if any) is reset to none. 15 | | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); 16 | | 17 | | /// @dev This emits when the approved address for an NFT is changed or 18 | | /// reaffirmed. The zero address indicates there is no approved address. 19 | | /// When a Transfer event emits, this also indicates that the approved 20 | | /// address for that NFT (if any) is reset to none. 21 | | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); 22 | | 23 | | /// @dev This emits when an operator is enabled or disabled for an owner. 24 | | /// The operator can manage all NFTs of the owner. 25 | | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 26 | | 27 | | /// @notice Count all NFTs assigned to an owner 28 | | /// @dev NFTs assigned to the zero address are considered invalid, and this 29 | | /// function throws for queries about the zero address. 30 | | /// @param _owner An address for whom to query the balance 31 | | /// @return The number of NFTs owned by `_owner`, possibly zero 32 | | function balanceOf(address _owner) external view returns (uint256); 33 | | 34 | | /// @notice Find the owner of an NFT 35 | | /// @dev NFTs assigned to zero address are considered invalid, and queries 36 | | /// about them do throw. 37 | | /// @param _tokenId The identifier for an NFT 38 | | /// @return The address of the owner of the NFT 39 | | function ownerOf(uint256 _tokenId) external view returns (address); 40 | | 41 | | /// @notice Transfers the ownership of an NFT from one address to another address 42 | | /// @dev Throws unless `msg.sender` is the current owner, an authorized 43 | | /// operator, or the approved address for this NFT. Throws if `_from` is 44 | | /// not the current owner. Throws if `_to` is the zero address. Throws if 45 | | /// `_tokenId` is not a valid NFT. When transfer is complete, this function 46 | | /// checks if `_to` is a smart contract (code size > 0). If so, it calls 47 | | /// `onERC721Received` on `_to` and throws if the return value is not 48 | | /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. 49 | | /// @param _from The current owner of the NFT 50 | | /// @param _to The new owner 51 | | /// @param _tokenId The NFT to transfer 52 | | /// @param data Additional data with no specified format, sent in call to `_to` 53 | | function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; 54 | | 55 | | /// @notice Transfers the ownership of an NFT from one address to another address 56 | | /// @dev This works identically to the other function with an extra data parameter, 57 | | /// except this function just sets data to "". 58 | | /// @param _from The current owner of the NFT 59 | | /// @param _to The new owner 60 | | /// @param _tokenId The NFT to transfer 61 | | function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; 62 | | 63 | | /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE 64 | | /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE 65 | | /// THEY MAY BE PERMANENTLY LOST 66 | | /// @dev Throws unless `msg.sender` is the current owner, an authorized 67 | | /// operator, or the approved address for this NFT. Throws if `_from` is 68 | | /// not the current owner. Throws if `_to` is the zero address. Throws if 69 | | /// `_tokenId` is not a valid NFT. 70 | | /// @param _from The current owner of the NFT 71 | | /// @param _to The new owner 72 | | /// @param _tokenId The NFT to transfer 73 | | function transferFrom(address _from, address _to, uint256 _tokenId) external payable; 74 | | 75 | | /// @notice Change or reaffirm the approved address for an NFT 76 | | /// @dev The zero address indicates there is no approved address. 77 | | /// Throws unless `msg.sender` is the current NFT owner, or an authorized 78 | | /// operator of the current owner. 79 | | /// @param _approved The new approved NFT controller 80 | | /// @param _tokenId The NFT to approve 81 | | function approve(address _approved, uint256 _tokenId) external payable; 82 | | 83 | | /// @notice Enable or disable approval for a third party ("operator") to manage 84 | | /// all of `msg.sender`'s assets 85 | | /// @dev Emits the ApprovalForAll event. The contract MUST allow 86 | | /// multiple operators per owner. 87 | | /// @param _operator Address to add to the set of authorized operators 88 | | /// @param _approved True if the operator is approved, false to revoke approval 89 | | function setApprovalForAll(address _operator, bool _approved) external; 90 | | 91 | | /// @notice Get the approved address for a single NFT 92 | | /// @dev Throws if `_tokenId` is not a valid NFT. 93 | | /// @param _tokenId The NFT to find the approved address for 94 | | /// @return The approved address for this NFT, or the zero address if there is none 95 | | function getApproved(uint256 _tokenId) external view returns (address); 96 | | 97 | | /// @notice Query if an address is an authorized operator for another address 98 | | /// @param _owner The address that owns the NFTs 99 | | /// @param _operator The address that acts on behalf of the owner 100 | | /// @return True if `_operator` is an approved operator for `_owner`, false otherwise 101 | | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 102 | | } 103 | | 104 | | /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. 105 | | interface IERC721TokenReceiver { 106 | | /// @notice Handle the receipt of an NFT 107 | | /// @dev The ERC721 smart contract calls this function on the recipient 108 | | /// after a `transfer`. This function MAY throw to revert and reject the 109 | | /// transfer. Return of other than the magic value MUST result in the 110 | | /// transaction being reverted. 111 | | /// Note: the contract address is always the message sender. 112 | | /// @param _operator The address which called `safeTransferFrom` function 113 | | /// @param _from The address which previously owned the token 114 | | /// @param _tokenId The NFT identifier which is being transferred 115 | | /// @param _data Additional data with no specified format 116 | | /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 117 | | /// unless throwing 118 | | function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) 119 | | external 120 | | returns (bytes4); 121 | | } 122 | | 123 | | /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension 124 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721 125 | | /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. 126 | | interface IERC721Metadata is IERC721 { 127 | | /// @notice A descriptive name for a collection of NFTs in this contract 128 | | function name() external view returns (string memory _name); 129 | | 130 | | /// @notice An abbreviated name for NFTs in this contract 131 | | function symbol() external view returns (string memory _symbol); 132 | | 133 | | /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. 134 | | /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC 135 | | /// 3986. The URI may point to a JSON file that conforms to the "ERC721 136 | | /// Metadata JSON Schema". 137 | | function tokenURI(uint256 _tokenId) external view returns (string memory); 138 | | } 139 | | 140 | | /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 141 | | /// @dev See https://eips.ethereum.org/EIPS/eip-721 142 | | /// Note: the ERC-165 identifier for this interface is 0x780e9d63. 143 | | interface IERC721Enumerable is IERC721 { 144 | | /// @notice Count NFTs tracked by this contract 145 | | /// @return A count of valid NFTs tracked by this contract, where each one of 146 | | /// them has an assigned and queryable owner not equal to the zero address 147 | | function totalSupply() external view returns (uint256); 148 | | 149 | | /// @notice Enumerate valid NFTs 150 | | /// @dev Throws if `_index` >= `totalSupply()`. 151 | | /// @param _index A counter less than `totalSupply()` 152 | | /// @return The token identifier for the `_index`th NFT, 153 | | /// (sort order not specified) 154 | | function tokenByIndex(uint256 _index) external view returns (uint256); 155 | | 156 | | /// @notice Enumerate NFTs assigned to an owner 157 | | /// @dev Throws if `_index` >= `balanceOf(_owner)` or if 158 | | /// `_owner` is the zero address, representing invalid NFTs. 159 | | /// @param _owner An address where we are interested in NFTs owned by them 160 | | /// @param _index A counter less than `balanceOf(_owner)` 161 | | /// @return The token identifier for the `_index`th NFT assigned to `_owner`, 162 | | /// (sort order not specified) 163 | | function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); 164 | | } 165 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/interfaces/IMulticall3.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | pragma experimental ABIEncoderV2; 5 | | 6 | | interface IMulticall3 { 7 | | struct Call { 8 | | address target; 9 | | bytes callData; 10 | | } 11 | | 12 | | struct Call3 { 13 | | address target; 14 | | bool allowFailure; 15 | | bytes callData; 16 | | } 17 | | 18 | | struct Call3Value { 19 | | address target; 20 | | bool allowFailure; 21 | | uint256 value; 22 | | bytes callData; 23 | | } 24 | | 25 | | struct Result { 26 | | bool success; 27 | | bytes returnData; 28 | | } 29 | | 30 | | function aggregate(Call[] calldata calls) 31 | | external 32 | | payable 33 | | returns (uint256 blockNumber, bytes[] memory returnData); 34 | | 35 | | function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); 36 | | 37 | | function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); 38 | | 39 | | function blockAndAggregate(Call[] calldata calls) 40 | | external 41 | | payable 42 | | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); 43 | | 44 | | function getBasefee() external view returns (uint256 basefee); 45 | | 46 | | function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); 47 | | 48 | | function getBlockNumber() external view returns (uint256 blockNumber); 49 | | 50 | | function getChainId() external view returns (uint256 chainid); 51 | | 52 | | function getCurrentBlockCoinbase() external view returns (address coinbase); 53 | | 54 | | function getCurrentBlockDifficulty() external view returns (uint256 difficulty); 55 | | 56 | | function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); 57 | | 58 | | function getCurrentBlockTimestamp() external view returns (uint256 timestamp); 59 | | 60 | | function getEthBalance(address addr) external view returns (uint256 balance); 61 | | 62 | | function getLastBlockHash() external view returns (bytes32 blockHash); 63 | | 64 | | function tryAggregate(bool requireSuccess, Call[] calldata calls) 65 | | external 66 | | payable 67 | | returns (Result[] memory returnData); 68 | | 69 | | function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) 70 | | external 71 | | payable 72 | | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); 73 | | } 74 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/mocks/MockERC20.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | import {IERC20} from "../interfaces/IERC20.sol"; 5 | | 6 | | /// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. 7 | | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol 8 | | contract MockERC20 is IERC20 { 9 | | /*////////////////////////////////////////////////////////////// 10 | | METADATA STORAGE 11 | | //////////////////////////////////////////////////////////////*/ 12 | | 13 | | string internal _name; 14 | | 15 | | string internal _symbol; 16 | | 17 | | uint8 internal _decimals; 18 | | 19 | | function name() external view override returns (string memory) { 20 | | return _name; 21 | | } 22 | | 23 | | function symbol() external view override returns (string memory) { 24 | | return _symbol; 25 | | } 26 | | 27 | | function decimals() external view override returns (uint8) { 28 | | return _decimals; 29 | | } 30 | | 31 | | /*////////////////////////////////////////////////////////////// 32 | | ERC20 STORAGE 33 | | //////////////////////////////////////////////////////////////*/ 34 | | 35 | | uint256 internal _totalSupply; 36 | | 37 | | mapping(address => uint256) internal _balanceOf; 38 | | 39 | | mapping(address => mapping(address => uint256)) internal _allowance; 40 | | 41 | | function totalSupply() external view override returns (uint256) { 42 | | return _totalSupply; 43 | | } 44 | | 45 | | function balanceOf(address owner) external view override returns (uint256) { 46 | | return _balanceOf[owner]; 47 | | } 48 | | 49 | | function allowance(address owner, address spender) external view override returns (uint256) { 50 | | return _allowance[owner][spender]; 51 | | } 52 | | 53 | | /*////////////////////////////////////////////////////////////// 54 | | EIP-2612 STORAGE 55 | | //////////////////////////////////////////////////////////////*/ 56 | | 57 | | uint256 internal INITIAL_CHAIN_ID; 58 | | 59 | | bytes32 internal INITIAL_DOMAIN_SEPARATOR; 60 | | 61 | | mapping(address => uint256) public nonces; 62 | | 63 | | /*////////////////////////////////////////////////////////////// 64 | | INITIALIZE 65 | | //////////////////////////////////////////////////////////////*/ 66 | | 67 | | /// @dev A bool to track whether the contract has been initialized. 68 | | bool private initialized; 69 | | 70 | | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 71 | | /// syntaxes, we add an initialization function that can be called only once. 72 | | function initialize(string memory name_, string memory symbol_, uint8 decimals_) public { 73 | | require(!initialized, "ALREADY_INITIALIZED"); 74 | | 75 | | _name = name_; 76 | | _symbol = symbol_; 77 | | _decimals = decimals_; 78 | | 79 | | INITIAL_CHAIN_ID = _pureChainId(); 80 | | INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); 81 | | 82 | | initialized = true; 83 | | } 84 | | 85 | | /*////////////////////////////////////////////////////////////// 86 | | ERC20 LOGIC 87 | | //////////////////////////////////////////////////////////////*/ 88 | | 89 | | function approve(address spender, uint256 amount) public virtual override returns (bool) { 90 | | _allowance[msg.sender][spender] = amount; 91 | | 92 | | emit Approval(msg.sender, spender, amount); 93 | | 94 | | return true; 95 | | } 96 | | 97 | | function transfer(address to, uint256 amount) public virtual override returns (bool) { 98 | | _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount); 99 | | _balanceOf[to] = _add(_balanceOf[to], amount); 100 | | 101 | | emit Transfer(msg.sender, to, amount); 102 | | 103 | | return true; 104 | | } 105 | | 106 | | function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { 107 | | uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals. 108 | | 109 | | if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount); 110 | | 111 | | _balanceOf[from] = _sub(_balanceOf[from], amount); 112 | | _balanceOf[to] = _add(_balanceOf[to], amount); 113 | | 114 | | emit Transfer(from, to, amount); 115 | | 116 | | return true; 117 | | } 118 | | 119 | | /*////////////////////////////////////////////////////////////// 120 | | EIP-2612 LOGIC 121 | | //////////////////////////////////////////////////////////////*/ 122 | | 123 | | function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) 124 | | public 125 | | virtual 126 | | { 127 | | require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); 128 | | 129 | | address recoveredAddress = ecrecover( 130 | | keccak256( 131 | | abi.encodePacked( 132 | | "\x19\x01", 133 | | DOMAIN_SEPARATOR(), 134 | | keccak256( 135 | | abi.encode( 136 | | keccak256( 137 | | "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" 138 | | ), 139 | | owner, 140 | | spender, 141 | | value, 142 | | nonces[owner]++, 143 | | deadline 144 | | ) 145 | | ) 146 | | ) 147 | | ), 148 | | v, 149 | | r, 150 | | s 151 | | ); 152 | | 153 | | require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); 154 | | 155 | | _allowance[recoveredAddress][spender] = value; 156 | | 157 | | emit Approval(owner, spender, value); 158 | | } 159 | | 160 | | function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { 161 | | return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); 162 | | } 163 | | 164 | | function computeDomainSeparator() internal view virtual returns (bytes32) { 165 | | return keccak256( 166 | | abi.encode( 167 | | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), 168 | | keccak256(bytes(_name)), 169 | | keccak256("1"), 170 | | _pureChainId(), 171 | | address(this) 172 | | ) 173 | | ); 174 | | } 175 | | 176 | | /*////////////////////////////////////////////////////////////// 177 | | INTERNAL MINT/BURN LOGIC 178 | | //////////////////////////////////////////////////////////////*/ 179 | | 180 | | function _mint(address to, uint256 amount) internal virtual { 181 | | _totalSupply = _add(_totalSupply, amount); 182 | | _balanceOf[to] = _add(_balanceOf[to], amount); 183 | | 184 | | emit Transfer(address(0), to, amount); 185 | | } 186 | | 187 | | function _burn(address from, uint256 amount) internal virtual { 188 | | _balanceOf[from] = _sub(_balanceOf[from], amount); 189 | | _totalSupply = _sub(_totalSupply, amount); 190 | | 191 | | emit Transfer(from, address(0), amount); 192 | | } 193 | | 194 | | /*////////////////////////////////////////////////////////////// 195 | | INTERNAL SAFE MATH LOGIC 196 | | //////////////////////////////////////////////////////////////*/ 197 | | 198 | | function _add(uint256 a, uint256 b) internal pure returns (uint256) { 199 | | uint256 c = a + b; 200 | | require(c >= a, "ERC20: addition overflow"); 201 | | return c; 202 | | } 203 | | 204 | | function _sub(uint256 a, uint256 b) internal pure returns (uint256) { 205 | | require(a >= b, "ERC20: subtraction underflow"); 206 | | return a - b; 207 | | } 208 | | 209 | | /*////////////////////////////////////////////////////////////// 210 | | HELPERS 211 | | //////////////////////////////////////////////////////////////*/ 212 | | 213 | | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no 214 | | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We 215 | | // can't simply access the chain ID in a normal view or pure function because the solc View Pure 216 | | // Checker changed `chainid` from pure to view in 0.8.0. 217 | | function _viewChainId() private view returns (uint256 chainId) { 218 | | // Assembly required since `block.chainid` was introduced in 0.8.0. 219 | | assembly { 220 | | chainId := chainid() 221 | | } 222 | | 223 | | address(this); // Silence warnings in older Solc versions. 224 | | } 225 | | 226 | | function _pureChainId() private pure returns (uint256 chainId) { 227 | | function() internal view returns (uint256) fnIn = _viewChainId; 228 | | function() internal pure returns (uint256) pureChainId; 229 | | assembly { 230 | | pureChainId := fnIn 231 | | } 232 | | chainId = pureChainId(); 233 | | } 234 | | } 235 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/mocks/MockERC721.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol"; 5 | | 6 | | /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. 7 | | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol 8 | | contract MockERC721 is IERC721Metadata { 9 | | /*////////////////////////////////////////////////////////////// 10 | | METADATA STORAGE/LOGIC 11 | | //////////////////////////////////////////////////////////////*/ 12 | | 13 | | string internal _name; 14 | | 15 | | string internal _symbol; 16 | | 17 | | function name() external view override returns (string memory) { 18 | | return _name; 19 | | } 20 | | 21 | | function symbol() external view override returns (string memory) { 22 | | return _symbol; 23 | | } 24 | | 25 | | function tokenURI(uint256 id) public view virtual override returns (string memory) {} 26 | | 27 | | /*////////////////////////////////////////////////////////////// 28 | | ERC721 BALANCE/OWNER STORAGE 29 | | //////////////////////////////////////////////////////////////*/ 30 | | 31 | | mapping(uint256 => address) internal _ownerOf; 32 | | 33 | | mapping(address => uint256) internal _balanceOf; 34 | | 35 | | function ownerOf(uint256 id) public view virtual override returns (address owner) { 36 | | require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); 37 | | } 38 | | 39 | | function balanceOf(address owner) public view virtual override returns (uint256) { 40 | | require(owner != address(0), "ZERO_ADDRESS"); 41 | | 42 | | return _balanceOf[owner]; 43 | | } 44 | | 45 | | /*////////////////////////////////////////////////////////////// 46 | | ERC721 APPROVAL STORAGE 47 | | //////////////////////////////////////////////////////////////*/ 48 | | 49 | | mapping(uint256 => address) internal _getApproved; 50 | | 51 | | mapping(address => mapping(address => bool)) internal _isApprovedForAll; 52 | | 53 | | function getApproved(uint256 id) public view virtual override returns (address) { 54 | | return _getApproved[id]; 55 | | } 56 | | 57 | | function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { 58 | | return _isApprovedForAll[owner][operator]; 59 | | } 60 | | 61 | | /*////////////////////////////////////////////////////////////// 62 | | INITIALIZE 63 | | //////////////////////////////////////////////////////////////*/ 64 | | 65 | | /// @dev A bool to track whether the contract has been initialized. 66 | | bool private initialized; 67 | | 68 | | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 69 | | /// syntaxes, we add an initialization function that can be called only once. 70 | | function initialize(string memory name_, string memory symbol_) public { 71 | | require(!initialized, "ALREADY_INITIALIZED"); 72 | | 73 | | _name = name_; 74 | | _symbol = symbol_; 75 | | 76 | | initialized = true; 77 | | } 78 | | 79 | | /*////////////////////////////////////////////////////////////// 80 | | ERC721 LOGIC 81 | | //////////////////////////////////////////////////////////////*/ 82 | | 83 | | function approve(address spender, uint256 id) public payable virtual override { 84 | | address owner = _ownerOf[id]; 85 | | 86 | | require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); 87 | | 88 | | _getApproved[id] = spender; 89 | | 90 | | emit Approval(owner, spender, id); 91 | | } 92 | | 93 | | function setApprovalForAll(address operator, bool approved) public virtual override { 94 | | _isApprovedForAll[msg.sender][operator] = approved; 95 | | 96 | | emit ApprovalForAll(msg.sender, operator, approved); 97 | | } 98 | | 99 | | function transferFrom(address from, address to, uint256 id) public payable virtual override { 100 | | require(from == _ownerOf[id], "WRONG_FROM"); 101 | | 102 | | require(to != address(0), "INVALID_RECIPIENT"); 103 | | 104 | | require( 105 | | msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id], 106 | | "NOT_AUTHORIZED" 107 | | ); 108 | | 109 | | // Underflow of the sender's balance is impossible because we check for 110 | | // ownership above and the recipient's balance can't realistically overflow. 111 | | _balanceOf[from]--; 112 | | 113 | | _balanceOf[to]++; 114 | | 115 | | _ownerOf[id] = to; 116 | | 117 | | delete _getApproved[id]; 118 | | 119 | | emit Transfer(from, to, id); 120 | | } 121 | | 122 | | function safeTransferFrom(address from, address to, uint256 id) public payable virtual override { 123 | | transferFrom(from, to, id); 124 | | 125 | | require( 126 | | !_isContract(to) 127 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") 128 | | == IERC721TokenReceiver.onERC721Received.selector, 129 | | "UNSAFE_RECIPIENT" 130 | | ); 131 | | } 132 | | 133 | | function safeTransferFrom(address from, address to, uint256 id, bytes memory data) 134 | | public 135 | | payable 136 | | virtual 137 | | override 138 | | { 139 | | transferFrom(from, to, id); 140 | | 141 | | require( 142 | | !_isContract(to) 143 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) 144 | | == IERC721TokenReceiver.onERC721Received.selector, 145 | | "UNSAFE_RECIPIENT" 146 | | ); 147 | | } 148 | | 149 | | /*////////////////////////////////////////////////////////////// 150 | | ERC165 LOGIC 151 | | //////////////////////////////////////////////////////////////*/ 152 | | 153 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 154 | | return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 155 | | || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 156 | | || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata 157 | | } 158 | | 159 | | /*////////////////////////////////////////////////////////////// 160 | | INTERNAL MINT/BURN LOGIC 161 | | //////////////////////////////////////////////////////////////*/ 162 | | 163 | | function _mint(address to, uint256 id) internal virtual { 164 | | require(to != address(0), "INVALID_RECIPIENT"); 165 | | 166 | | require(_ownerOf[id] == address(0), "ALREADY_MINTED"); 167 | | 168 | | // Counter overflow is incredibly unrealistic. 169 | | 170 | | _balanceOf[to]++; 171 | | 172 | | _ownerOf[id] = to; 173 | | 174 | | emit Transfer(address(0), to, id); 175 | | } 176 | | 177 | | function _burn(uint256 id) internal virtual { 178 | | address owner = _ownerOf[id]; 179 | | 180 | | require(owner != address(0), "NOT_MINTED"); 181 | | 182 | | _balanceOf[owner]--; 183 | | 184 | | delete _ownerOf[id]; 185 | | 186 | | delete _getApproved[id]; 187 | | 188 | | emit Transfer(owner, address(0), id); 189 | | } 190 | | 191 | | /*////////////////////////////////////////////////////////////// 192 | | INTERNAL SAFE MINT LOGIC 193 | | //////////////////////////////////////////////////////////////*/ 194 | | 195 | | function _safeMint(address to, uint256 id) internal virtual { 196 | | _mint(to, id); 197 | | 198 | | require( 199 | | !_isContract(to) 200 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") 201 | | == IERC721TokenReceiver.onERC721Received.selector, 202 | | "UNSAFE_RECIPIENT" 203 | | ); 204 | | } 205 | | 206 | | function _safeMint(address to, uint256 id, bytes memory data) internal virtual { 207 | | _mint(to, id); 208 | | 209 | | require( 210 | | !_isContract(to) 211 | | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) 212 | | == IERC721TokenReceiver.onERC721Received.selector, 213 | | "UNSAFE_RECIPIENT" 214 | | ); 215 | | } 216 | | 217 | | /*////////////////////////////////////////////////////////////// 218 | | HELPERS 219 | | //////////////////////////////////////////////////////////////*/ 220 | | 221 | | function _isContract(address _addr) private view returns (bool) { 222 | | uint256 codeLength; 223 | | 224 | | // Assembly required for versions < 0.8.0 to check extcodesize. 225 | | assembly { 226 | | codeLength := extcodesize(_addr) 227 | | } 228 | | 229 | | return codeLength > 0; 230 | | } 231 | | } 232 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/forge-std/src/safeconsole.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity >=0.6.2 <0.9.0; 3 | | 4 | | /// @author philogy <https://github.com/philogy> 5 | | /// @dev Code generated automatically by script. 6 | * | library safeconsole { 7 | | uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67; 8 | | 9 | | // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374) 10 | | // for the view-to-pure log trick. 11 | | function _sendLogPayload(uint256 offset, uint256 size) private pure { 12 | | function(uint256, uint256) internal view fnIn = _sendLogPayloadView; 13 | | function(uint256, uint256) internal pure pureSendLogPayload; 14 | | /// @solidity memory-safe-assembly 15 | | assembly { 16 | | pureSendLogPayload := fnIn 17 | | } 18 | | pureSendLogPayload(offset, size); 19 | | } 20 | | 21 | | function _sendLogPayloadView(uint256 offset, uint256 size) private view { 22 | | /// @solidity memory-safe-assembly 23 | | assembly { 24 | | pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0)) 25 | | } 26 | | } 27 | | 28 | | function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure { 29 | | function(uint256, uint256, uint256) internal view fnIn = _memcopyView; 30 | | function(uint256, uint256, uint256) internal pure pureMemcopy; 31 | | /// @solidity memory-safe-assembly 32 | | assembly { 33 | | pureMemcopy := fnIn 34 | | } 35 | | pureMemcopy(fromOffset, toOffset, length); 36 | | } 37 | | 38 | | function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view { 39 | | /// @solidity memory-safe-assembly 40 | | assembly { 41 | | pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length)) 42 | | } 43 | | } 44 | | 45 | | function logMemory(uint256 offset, uint256 length) internal pure { 46 | | if (offset >= 0x60) { 47 | | // Sufficient memory before slice to prepare call header. 48 | | bytes32 m0; 49 | | bytes32 m1; 50 | | bytes32 m2; 51 | | /// @solidity memory-safe-assembly 52 | | assembly { 53 | | m0 := mload(sub(offset, 0x60)) 54 | | m1 := mload(sub(offset, 0x40)) 55 | | m2 := mload(sub(offset, 0x20)) 56 | | // Selector of `log(bytes)`. 57 | | mstore(sub(offset, 0x60), 0x0be77f56) 58 | | mstore(sub(offset, 0x40), 0x20) 59 | | mstore(sub(offset, 0x20), length) 60 | | } 61 | | _sendLogPayload(offset - 0x44, length + 0x44); 62 | | /// @solidity memory-safe-assembly 63 | | assembly { 64 | | mstore(sub(offset, 0x60), m0) 65 | | mstore(sub(offset, 0x40), m1) 66 | | mstore(sub(offset, 0x20), m2) 67 | | } 68 | | } else { 69 | | // Insufficient space, so copy slice forward, add header and reverse. 70 | | bytes32 m0; 71 | | bytes32 m1; 72 | | bytes32 m2; 73 | | uint256 endOffset = offset + length; 74 | | /// @solidity memory-safe-assembly 75 | | assembly { 76 | | m0 := mload(add(endOffset, 0x00)) 77 | | m1 := mload(add(endOffset, 0x20)) 78 | | m2 := mload(add(endOffset, 0x40)) 79 | | } 80 | | _memcopy(offset, offset + 0x60, length); 81 | | /// @solidity memory-safe-assembly 82 | | assembly { 83 | | // Selector of `log(bytes)`. 84 | | mstore(add(offset, 0x00), 0x0be77f56) 85 | | mstore(add(offset, 0x20), 0x20) 86 | | mstore(add(offset, 0x40), length) 87 | | } 88 | | _sendLogPayload(offset + 0x1c, length + 0x44); 89 | | _memcopy(offset + 0x60, offset, length); 90 | | /// @solidity memory-safe-assembly 91 | | assembly { 92 | | mstore(add(endOffset, 0x00), m0) 93 | | mstore(add(endOffset, 0x20), m1) 94 | | mstore(add(endOffset, 0x40), m2) 95 | | } 96 | | } 97 | | } 98 | | 99 | | function log(address p0) internal pure { 100 | | bytes32 m0; 101 | | bytes32 m1; 102 | | /// @solidity memory-safe-assembly 103 | | assembly { 104 | | m0 := mload(0x00) 105 | | m1 := mload(0x20) 106 | | // Selector of `log(address)`. 107 | | mstore(0x00, 0x2c2ecbc2) 108 | | mstore(0x20, p0) 109 | | } 110 | | _sendLogPayload(0x1c, 0x24); 111 | | /// @solidity memory-safe-assembly 112 | | assembly { 113 | | mstore(0x00, m0) 114 | | mstore(0x20, m1) 115 | | } 116 | | } 117 | | 118 | | function log(bool p0) internal pure { 119 | | bytes32 m0; 120 | | bytes32 m1; 121 | | /// @solidity memory-safe-assembly 122 | | assembly { 123 | | m0 := mload(0x00) 124 | | m1 := mload(0x20) 125 | | // Selector of `log(bool)`. 126 | | mstore(0x00, 0x32458eed) 127 | | mstore(0x20, p0) 128 | | } 129 | | _sendLogPayload(0x1c, 0x24); 130 | | /// @solidity memory-safe-assembly 131 | | assembly { 132 | | mstore(0x00, m0) 133 | | mstore(0x20, m1) 134 | | } 135 | | } 136 | | 137 | | function log(uint256 p0) internal pure { 138 | | bytes32 m0; 139 | | bytes32 m1; 140 | | /// @solidity memory-safe-assembly 141 | | assembly { 142 | | m0 := mload(0x00) 143 | | m1 := mload(0x20) 144 | | // Selector of `log(uint256)`. 145 | | mstore(0x00, 0xf82c50f1) 146 | | mstore(0x20, p0) 147 | | } 148 | | _sendLogPayload(0x1c, 0x24); 149 | | /// @solidity memory-safe-assembly 150 | | assembly { 151 | | mstore(0x00, m0) 152 | | mstore(0x20, m1) 153 | | } 154 | | } 155 | | 156 | | function log(bytes32 p0) internal pure { 157 | | bytes32 m0; 158 | | bytes32 m1; 159 | | bytes32 m2; 160 | | bytes32 m3; 161 | | /// @solidity memory-safe-assembly 162 | | assembly { 163 | | function writeString(pos, w) { 164 | | let length := 0 165 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 166 | | mstore(pos, length) 167 | | let shift := sub(256, shl(3, length)) 168 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 169 | | } 170 | | m0 := mload(0x00) 171 | | m1 := mload(0x20) 172 | | m2 := mload(0x40) 173 | | m3 := mload(0x60) 174 | | // Selector of `log(string)`. 175 | | mstore(0x00, 0x41304fac) 176 | | mstore(0x20, 0x20) 177 | | writeString(0x40, p0) 178 | | } 179 | | _sendLogPayload(0x1c, 0x64); 180 | | /// @solidity memory-safe-assembly 181 | | assembly { 182 | | mstore(0x00, m0) 183 | | mstore(0x20, m1) 184 | | mstore(0x40, m2) 185 | | mstore(0x60, m3) 186 | | } 187 | | } 188 | | 189 | | function log(address p0, address p1) internal pure { 190 | | bytes32 m0; 191 | | bytes32 m1; 192 | | bytes32 m2; 193 | | /// @solidity memory-safe-assembly 194 | | assembly { 195 | | m0 := mload(0x00) 196 | | m1 := mload(0x20) 197 | | m2 := mload(0x40) 198 | | // Selector of `log(address,address)`. 199 | | mstore(0x00, 0xdaf0d4aa) 200 | | mstore(0x20, p0) 201 | | mstore(0x40, p1) 202 | | } 203 | | _sendLogPayload(0x1c, 0x44); 204 | | /// @solidity memory-safe-assembly 205 | | assembly { 206 | | mstore(0x00, m0) 207 | | mstore(0x20, m1) 208 | | mstore(0x40, m2) 209 | | } 210 | | } 211 | | 212 | | function log(address p0, bool p1) internal pure { 213 | | bytes32 m0; 214 | | bytes32 m1; 215 | | bytes32 m2; 216 | | /// @solidity memory-safe-assembly 217 | | assembly { 218 | | m0 := mload(0x00) 219 | | m1 := mload(0x20) 220 | | m2 := mload(0x40) 221 | | // Selector of `log(address,bool)`. 222 | | mstore(0x00, 0x75b605d3) 223 | | mstore(0x20, p0) 224 | | mstore(0x40, p1) 225 | | } 226 | | _sendLogPayload(0x1c, 0x44); 227 | | /// @solidity memory-safe-assembly 228 | | assembly { 229 | | mstore(0x00, m0) 230 | | mstore(0x20, m1) 231 | | mstore(0x40, m2) 232 | | } 233 | | } 234 | | 235 | | function log(address p0, uint256 p1) internal pure { 236 | | bytes32 m0; 237 | | bytes32 m1; 238 | | bytes32 m2; 239 | | /// @solidity memory-safe-assembly 240 | | assembly { 241 | | m0 := mload(0x00) 242 | | m1 := mload(0x20) 243 | | m2 := mload(0x40) 244 | | // Selector of `log(address,uint256)`. 245 | | mstore(0x00, 0x8309e8a8) 246 | | mstore(0x20, p0) 247 | | mstore(0x40, p1) 248 | | } 249 | | _sendLogPayload(0x1c, 0x44); 250 | | /// @solidity memory-safe-assembly 251 | | assembly { 252 | | mstore(0x00, m0) 253 | | mstore(0x20, m1) 254 | | mstore(0x40, m2) 255 | | } 256 | | } 257 | | 258 | | function log(address p0, bytes32 p1) internal pure { 259 | | bytes32 m0; 260 | | bytes32 m1; 261 | | bytes32 m2; 262 | | bytes32 m3; 263 | | bytes32 m4; 264 | | /// @solidity memory-safe-assembly 265 | | assembly { 266 | | function writeString(pos, w) { 267 | | let length := 0 268 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 269 | | mstore(pos, length) 270 | | let shift := sub(256, shl(3, length)) 271 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 272 | | } 273 | | m0 := mload(0x00) 274 | | m1 := mload(0x20) 275 | | m2 := mload(0x40) 276 | | m3 := mload(0x60) 277 | | m4 := mload(0x80) 278 | | // Selector of `log(address,string)`. 279 | | mstore(0x00, 0x759f86bb) 280 | | mstore(0x20, p0) 281 | | mstore(0x40, 0x40) 282 | | writeString(0x60, p1) 283 | | } 284 | | _sendLogPayload(0x1c, 0x84); 285 | | /// @solidity memory-safe-assembly 286 | | assembly { 287 | | mstore(0x00, m0) 288 | | mstore(0x20, m1) 289 | | mstore(0x40, m2) 290 | | mstore(0x60, m3) 291 | | mstore(0x80, m4) 292 | | } 293 | | } 294 | | 295 | | function log(bool p0, address p1) internal pure { 296 | | bytes32 m0; 297 | | bytes32 m1; 298 | | bytes32 m2; 299 | | /// @solidity memory-safe-assembly 300 | | assembly { 301 | | m0 := mload(0x00) 302 | | m1 := mload(0x20) 303 | | m2 := mload(0x40) 304 | | // Selector of `log(bool,address)`. 305 | | mstore(0x00, 0x853c4849) 306 | | mstore(0x20, p0) 307 | | mstore(0x40, p1) 308 | | } 309 | | _sendLogPayload(0x1c, 0x44); 310 | | /// @solidity memory-safe-assembly 311 | | assembly { 312 | | mstore(0x00, m0) 313 | | mstore(0x20, m1) 314 | | mstore(0x40, m2) 315 | | } 316 | | } 317 | | 318 | | function log(bool p0, bool p1) internal pure { 319 | | bytes32 m0; 320 | | bytes32 m1; 321 | | bytes32 m2; 322 | | /// @solidity memory-safe-assembly 323 | | assembly { 324 | | m0 := mload(0x00) 325 | | m1 := mload(0x20) 326 | | m2 := mload(0x40) 327 | | // Selector of `log(bool,bool)`. 328 | | mstore(0x00, 0x2a110e83) 329 | | mstore(0x20, p0) 330 | | mstore(0x40, p1) 331 | | } 332 | | _sendLogPayload(0x1c, 0x44); 333 | | /// @solidity memory-safe-assembly 334 | | assembly { 335 | | mstore(0x00, m0) 336 | | mstore(0x20, m1) 337 | | mstore(0x40, m2) 338 | | } 339 | | } 340 | | 341 | | function log(bool p0, uint256 p1) internal pure { 342 | | bytes32 m0; 343 | | bytes32 m1; 344 | | bytes32 m2; 345 | | /// @solidity memory-safe-assembly 346 | | assembly { 347 | | m0 := mload(0x00) 348 | | m1 := mload(0x20) 349 | | m2 := mload(0x40) 350 | | // Selector of `log(bool,uint256)`. 351 | | mstore(0x00, 0x399174d3) 352 | | mstore(0x20, p0) 353 | | mstore(0x40, p1) 354 | | } 355 | | _sendLogPayload(0x1c, 0x44); 356 | | /// @solidity memory-safe-assembly 357 | | assembly { 358 | | mstore(0x00, m0) 359 | | mstore(0x20, m1) 360 | | mstore(0x40, m2) 361 | | } 362 | | } 363 | | 364 | | function log(bool p0, bytes32 p1) internal pure { 365 | | bytes32 m0; 366 | | bytes32 m1; 367 | | bytes32 m2; 368 | | bytes32 m3; 369 | | bytes32 m4; 370 | | /// @solidity memory-safe-assembly 371 | | assembly { 372 | | function writeString(pos, w) { 373 | | let length := 0 374 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 375 | | mstore(pos, length) 376 | | let shift := sub(256, shl(3, length)) 377 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 378 | | } 379 | | m0 := mload(0x00) 380 | | m1 := mload(0x20) 381 | | m2 := mload(0x40) 382 | | m3 := mload(0x60) 383 | | m4 := mload(0x80) 384 | | // Selector of `log(bool,string)`. 385 | | mstore(0x00, 0x8feac525) 386 | | mstore(0x20, p0) 387 | | mstore(0x40, 0x40) 388 | | writeString(0x60, p1) 389 | | } 390 | | _sendLogPayload(0x1c, 0x84); 391 | | /// @solidity memory-safe-assembly 392 | | assembly { 393 | | mstore(0x00, m0) 394 | | mstore(0x20, m1) 395 | | mstore(0x40, m2) 396 | | mstore(0x60, m3) 397 | | mstore(0x80, m4) 398 | | } 399 | | } 400 | | 401 | | function log(uint256 p0, address p1) internal pure { 402 | | bytes32 m0; 403 | | bytes32 m1; 404 | | bytes32 m2; 405 | | /// @solidity memory-safe-assembly 406 | | assembly { 407 | | m0 := mload(0x00) 408 | | m1 := mload(0x20) 409 | | m2 := mload(0x40) 410 | | // Selector of `log(uint256,address)`. 411 | | mstore(0x00, 0x69276c86) 412 | | mstore(0x20, p0) 413 | | mstore(0x40, p1) 414 | | } 415 | | _sendLogPayload(0x1c, 0x44); 416 | | /// @solidity memory-safe-assembly 417 | | assembly { 418 | | mstore(0x00, m0) 419 | | mstore(0x20, m1) 420 | | mstore(0x40, m2) 421 | | } 422 | | } 423 | | 424 | | function log(uint256 p0, bool p1) internal pure { 425 | | bytes32 m0; 426 | | bytes32 m1; 427 | | bytes32 m2; 428 | | /// @solidity memory-safe-assembly 429 | | assembly { 430 | | m0 := mload(0x00) 431 | | m1 := mload(0x20) 432 | | m2 := mload(0x40) 433 | | // Selector of `log(uint256,bool)`. 434 | | mstore(0x00, 0x1c9d7eb3) 435 | | mstore(0x20, p0) 436 | | mstore(0x40, p1) 437 | | } 438 | | _sendLogPayload(0x1c, 0x44); 439 | | /// @solidity memory-safe-assembly 440 | | assembly { 441 | | mstore(0x00, m0) 442 | | mstore(0x20, m1) 443 | | mstore(0x40, m2) 444 | | } 445 | | } 446 | | 447 | | function log(uint256 p0, uint256 p1) internal pure { 448 | | bytes32 m0; 449 | | bytes32 m1; 450 | | bytes32 m2; 451 | | /// @solidity memory-safe-assembly 452 | | assembly { 453 | | m0 := mload(0x00) 454 | | m1 := mload(0x20) 455 | | m2 := mload(0x40) 456 | | // Selector of `log(uint256,uint256)`. 457 | | mstore(0x00, 0xf666715a) 458 | | mstore(0x20, p0) 459 | | mstore(0x40, p1) 460 | | } 461 | | _sendLogPayload(0x1c, 0x44); 462 | | /// @solidity memory-safe-assembly 463 | | assembly { 464 | | mstore(0x00, m0) 465 | | mstore(0x20, m1) 466 | | mstore(0x40, m2) 467 | | } 468 | | } 469 | | 470 | | function log(uint256 p0, bytes32 p1) internal pure { 471 | | bytes32 m0; 472 | | bytes32 m1; 473 | | bytes32 m2; 474 | | bytes32 m3; 475 | | bytes32 m4; 476 | | /// @solidity memory-safe-assembly 477 | | assembly { 478 | | function writeString(pos, w) { 479 | | let length := 0 480 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 481 | | mstore(pos, length) 482 | | let shift := sub(256, shl(3, length)) 483 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 484 | | } 485 | | m0 := mload(0x00) 486 | | m1 := mload(0x20) 487 | | m2 := mload(0x40) 488 | | m3 := mload(0x60) 489 | | m4 := mload(0x80) 490 | | // Selector of `log(uint256,string)`. 491 | | mstore(0x00, 0x643fd0df) 492 | | mstore(0x20, p0) 493 | | mstore(0x40, 0x40) 494 | | writeString(0x60, p1) 495 | | } 496 | | _sendLogPayload(0x1c, 0x84); 497 | | /// @solidity memory-safe-assembly 498 | | assembly { 499 | | mstore(0x00, m0) 500 | | mstore(0x20, m1) 501 | | mstore(0x40, m2) 502 | | mstore(0x60, m3) 503 | | mstore(0x80, m4) 504 | | } 505 | | } 506 | | 507 | | function log(bytes32 p0, address p1) internal pure { 508 | | bytes32 m0; 509 | | bytes32 m1; 510 | | bytes32 m2; 511 | | bytes32 m3; 512 | | bytes32 m4; 513 | | /// @solidity memory-safe-assembly 514 | | assembly { 515 | | function writeString(pos, w) { 516 | | let length := 0 517 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 518 | | mstore(pos, length) 519 | | let shift := sub(256, shl(3, length)) 520 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 521 | | } 522 | | m0 := mload(0x00) 523 | | m1 := mload(0x20) 524 | | m2 := mload(0x40) 525 | | m3 := mload(0x60) 526 | | m4 := mload(0x80) 527 | | // Selector of `log(string,address)`. 528 | | mstore(0x00, 0x319af333) 529 | | mstore(0x20, 0x40) 530 | | mstore(0x40, p1) 531 | | writeString(0x60, p0) 532 | | } 533 | | _sendLogPayload(0x1c, 0x84); 534 | | /// @solidity memory-safe-assembly 535 | | assembly { 536 | | mstore(0x00, m0) 537 | | mstore(0x20, m1) 538 | | mstore(0x40, m2) 539 | | mstore(0x60, m3) 540 | | mstore(0x80, m4) 541 | | } 542 | | } 543 | | 544 | | function log(bytes32 p0, bool p1) internal pure { 545 | | bytes32 m0; 546 | | bytes32 m1; 547 | | bytes32 m2; 548 | | bytes32 m3; 549 | | bytes32 m4; 550 | | /// @solidity memory-safe-assembly 551 | | assembly { 552 | | function writeString(pos, w) { 553 | | let length := 0 554 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 555 | | mstore(pos, length) 556 | | let shift := sub(256, shl(3, length)) 557 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 558 | | } 559 | | m0 := mload(0x00) 560 | | m1 := mload(0x20) 561 | | m2 := mload(0x40) 562 | | m3 := mload(0x60) 563 | | m4 := mload(0x80) 564 | | // Selector of `log(string,bool)`. 565 | | mstore(0x00, 0xc3b55635) 566 | | mstore(0x20, 0x40) 567 | | mstore(0x40, p1) 568 | | writeString(0x60, p0) 569 | | } 570 | | _sendLogPayload(0x1c, 0x84); 571 | | /// @solidity memory-safe-assembly 572 | | assembly { 573 | | mstore(0x00, m0) 574 | | mstore(0x20, m1) 575 | | mstore(0x40, m2) 576 | | mstore(0x60, m3) 577 | | mstore(0x80, m4) 578 | | } 579 | | } 580 | | 581 | | function log(bytes32 p0, uint256 p1) internal pure { 582 | | bytes32 m0; 583 | | bytes32 m1; 584 | | bytes32 m2; 585 | | bytes32 m3; 586 | | bytes32 m4; 587 | | /// @solidity memory-safe-assembly 588 | | assembly { 589 | | function writeString(pos, w) { 590 | | let length := 0 591 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 592 | | mstore(pos, length) 593 | | let shift := sub(256, shl(3, length)) 594 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 595 | | } 596 | | m0 := mload(0x00) 597 | | m1 := mload(0x20) 598 | | m2 := mload(0x40) 599 | | m3 := mload(0x60) 600 | | m4 := mload(0x80) 601 | | // Selector of `log(string,uint256)`. 602 | | mstore(0x00, 0xb60e72cc) 603 | | mstore(0x20, 0x40) 604 | | mstore(0x40, p1) 605 | | writeString(0x60, p0) 606 | | } 607 | | _sendLogPayload(0x1c, 0x84); 608 | | /// @solidity memory-safe-assembly 609 | | assembly { 610 | | mstore(0x00, m0) 611 | | mstore(0x20, m1) 612 | | mstore(0x40, m2) 613 | | mstore(0x60, m3) 614 | | mstore(0x80, m4) 615 | | } 616 | | } 617 | | 618 | | function log(bytes32 p0, bytes32 p1) internal pure { 619 | | bytes32 m0; 620 | | bytes32 m1; 621 | | bytes32 m2; 622 | | bytes32 m3; 623 | | bytes32 m4; 624 | | bytes32 m5; 625 | | bytes32 m6; 626 | | /// @solidity memory-safe-assembly 627 | | assembly { 628 | | function writeString(pos, w) { 629 | | let length := 0 630 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 631 | | mstore(pos, length) 632 | | let shift := sub(256, shl(3, length)) 633 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 634 | | } 635 | | m0 := mload(0x00) 636 | | m1 := mload(0x20) 637 | | m2 := mload(0x40) 638 | | m3 := mload(0x60) 639 | | m4 := mload(0x80) 640 | | m5 := mload(0xa0) 641 | | m6 := mload(0xc0) 642 | | // Selector of `log(string,string)`. 643 | | mstore(0x00, 0x4b5c4277) 644 | | mstore(0x20, 0x40) 645 | | mstore(0x40, 0x80) 646 | | writeString(0x60, p0) 647 | | writeString(0xa0, p1) 648 | | } 649 | | _sendLogPayload(0x1c, 0xc4); 650 | | /// @solidity memory-safe-assembly 651 | | assembly { 652 | | mstore(0x00, m0) 653 | | mstore(0x20, m1) 654 | | mstore(0x40, m2) 655 | | mstore(0x60, m3) 656 | | mstore(0x80, m4) 657 | | mstore(0xa0, m5) 658 | | mstore(0xc0, m6) 659 | | } 660 | | } 661 | | 662 | | function log(address p0, address p1, address p2) internal pure { 663 | | bytes32 m0; 664 | | bytes32 m1; 665 | | bytes32 m2; 666 | | bytes32 m3; 667 | | /// @solidity memory-safe-assembly 668 | | assembly { 669 | | m0 := mload(0x00) 670 | | m1 := mload(0x20) 671 | | m2 := mload(0x40) 672 | | m3 := mload(0x60) 673 | | // Selector of `log(address,address,address)`. 674 | | mstore(0x00, 0x018c84c2) 675 | | mstore(0x20, p0) 676 | | mstore(0x40, p1) 677 | | mstore(0x60, p2) 678 | | } 679 | | _sendLogPayload(0x1c, 0x64); 680 | | /// @solidity memory-safe-assembly 681 | | assembly { 682 | | mstore(0x00, m0) 683 | | mstore(0x20, m1) 684 | | mstore(0x40, m2) 685 | | mstore(0x60, m3) 686 | | } 687 | | } 688 | | 689 | | function log(address p0, address p1, bool p2) internal pure { 690 | | bytes32 m0; 691 | | bytes32 m1; 692 | | bytes32 m2; 693 | | bytes32 m3; 694 | | /// @solidity memory-safe-assembly 695 | | assembly { 696 | | m0 := mload(0x00) 697 | | m1 := mload(0x20) 698 | | m2 := mload(0x40) 699 | | m3 := mload(0x60) 700 | | // Selector of `log(address,address,bool)`. 701 | | mstore(0x00, 0xf2a66286) 702 | | mstore(0x20, p0) 703 | | mstore(0x40, p1) 704 | | mstore(0x60, p2) 705 | | } 706 | | _sendLogPayload(0x1c, 0x64); 707 | | /// @solidity memory-safe-assembly 708 | | assembly { 709 | | mstore(0x00, m0) 710 | | mstore(0x20, m1) 711 | | mstore(0x40, m2) 712 | | mstore(0x60, m3) 713 | | } 714 | | } 715 | | 716 | | function log(address p0, address p1, uint256 p2) internal pure { 717 | | bytes32 m0; 718 | | bytes32 m1; 719 | | bytes32 m2; 720 | | bytes32 m3; 721 | | /// @solidity memory-safe-assembly 722 | | assembly { 723 | | m0 := mload(0x00) 724 | | m1 := mload(0x20) 725 | | m2 := mload(0x40) 726 | | m3 := mload(0x60) 727 | | // Selector of `log(address,address,uint256)`. 728 | | mstore(0x00, 0x17fe6185) 729 | | mstore(0x20, p0) 730 | | mstore(0x40, p1) 731 | | mstore(0x60, p2) 732 | | } 733 | | _sendLogPayload(0x1c, 0x64); 734 | | /// @solidity memory-safe-assembly 735 | | assembly { 736 | | mstore(0x00, m0) 737 | | mstore(0x20, m1) 738 | | mstore(0x40, m2) 739 | | mstore(0x60, m3) 740 | | } 741 | | } 742 | | 743 | | function log(address p0, address p1, bytes32 p2) internal pure { 744 | | bytes32 m0; 745 | | bytes32 m1; 746 | | bytes32 m2; 747 | | bytes32 m3; 748 | | bytes32 m4; 749 | | bytes32 m5; 750 | | /// @solidity memory-safe-assembly 751 | | assembly { 752 | | function writeString(pos, w) { 753 | | let length := 0 754 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 755 | | mstore(pos, length) 756 | | let shift := sub(256, shl(3, length)) 757 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 758 | | } 759 | | m0 := mload(0x00) 760 | | m1 := mload(0x20) 761 | | m2 := mload(0x40) 762 | | m3 := mload(0x60) 763 | | m4 := mload(0x80) 764 | | m5 := mload(0xa0) 765 | | // Selector of `log(address,address,string)`. 766 | | mstore(0x00, 0x007150be) 767 | | mstore(0x20, p0) 768 | | mstore(0x40, p1) 769 | | mstore(0x60, 0x60) 770 | | writeString(0x80, p2) 771 | | } 772 | | _sendLogPayload(0x1c, 0xa4); 773 | | /// @solidity memory-safe-assembly 774 | | assembly { 775 | | mstore(0x00, m0) 776 | | mstore(0x20, m1) 777 | | mstore(0x40, m2) 778 | | mstore(0x60, m3) 779 | | mstore(0x80, m4) 780 | | mstore(0xa0, m5) 781 | | } 782 | | } 783 | | 784 | | function log(address p0, bool p1, address p2) internal pure { 785 | | bytes32 m0; 786 | | bytes32 m1; 787 | | bytes32 m2; 788 | | bytes32 m3; 789 | | /// @solidity memory-safe-assembly 790 | | assembly { 791 | | m0 := mload(0x00) 792 | | m1 := mload(0x20) 793 | | m2 := mload(0x40) 794 | | m3 := mload(0x60) 795 | | // Selector of `log(address,bool,address)`. 796 | | mstore(0x00, 0xf11699ed) 797 | | mstore(0x20, p0) 798 | | mstore(0x40, p1) 799 | | mstore(0x60, p2) 800 | | } 801 | | _sendLogPayload(0x1c, 0x64); 802 | | /// @solidity memory-safe-assembly 803 | | assembly { 804 | | mstore(0x00, m0) 805 | | mstore(0x20, m1) 806 | | mstore(0x40, m2) 807 | | mstore(0x60, m3) 808 | | } 809 | | } 810 | | 811 | | function log(address p0, bool p1, bool p2) internal pure { 812 | | bytes32 m0; 813 | | bytes32 m1; 814 | | bytes32 m2; 815 | | bytes32 m3; 816 | | /// @solidity memory-safe-assembly 817 | | assembly { 818 | | m0 := mload(0x00) 819 | | m1 := mload(0x20) 820 | | m2 := mload(0x40) 821 | | m3 := mload(0x60) 822 | | // Selector of `log(address,bool,bool)`. 823 | | mstore(0x00, 0xeb830c92) 824 | | mstore(0x20, p0) 825 | | mstore(0x40, p1) 826 | | mstore(0x60, p2) 827 | | } 828 | | _sendLogPayload(0x1c, 0x64); 829 | | /// @solidity memory-safe-assembly 830 | | assembly { 831 | | mstore(0x00, m0) 832 | | mstore(0x20, m1) 833 | | mstore(0x40, m2) 834 | | mstore(0x60, m3) 835 | | } 836 | | } 837 | | 838 | | function log(address p0, bool p1, uint256 p2) internal pure { 839 | | bytes32 m0; 840 | | bytes32 m1; 841 | | bytes32 m2; 842 | | bytes32 m3; 843 | | /// @solidity memory-safe-assembly 844 | | assembly { 845 | | m0 := mload(0x00) 846 | | m1 := mload(0x20) 847 | | m2 := mload(0x40) 848 | | m3 := mload(0x60) 849 | | // Selector of `log(address,bool,uint256)`. 850 | | mstore(0x00, 0x9c4f99fb) 851 | | mstore(0x20, p0) 852 | | mstore(0x40, p1) 853 | | mstore(0x60, p2) 854 | | } 855 | | _sendLogPayload(0x1c, 0x64); 856 | | /// @solidity memory-safe-assembly 857 | | assembly { 858 | | mstore(0x00, m0) 859 | | mstore(0x20, m1) 860 | | mstore(0x40, m2) 861 | | mstore(0x60, m3) 862 | | } 863 | | } 864 | | 865 | | function log(address p0, bool p1, bytes32 p2) internal pure { 866 | | bytes32 m0; 867 | | bytes32 m1; 868 | | bytes32 m2; 869 | | bytes32 m3; 870 | | bytes32 m4; 871 | | bytes32 m5; 872 | | /// @solidity memory-safe-assembly 873 | | assembly { 874 | | function writeString(pos, w) { 875 | | let length := 0 876 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 877 | | mstore(pos, length) 878 | | let shift := sub(256, shl(3, length)) 879 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 880 | | } 881 | | m0 := mload(0x00) 882 | | m1 := mload(0x20) 883 | | m2 := mload(0x40) 884 | | m3 := mload(0x60) 885 | | m4 := mload(0x80) 886 | | m5 := mload(0xa0) 887 | | // Selector of `log(address,bool,string)`. 888 | | mstore(0x00, 0x212255cc) 889 | | mstore(0x20, p0) 890 | | mstore(0x40, p1) 891 | | mstore(0x60, 0x60) 892 | | writeString(0x80, p2) 893 | | } 894 | | _sendLogPayload(0x1c, 0xa4); 895 | | /// @solidity memory-safe-assembly 896 | | assembly { 897 | | mstore(0x00, m0) 898 | | mstore(0x20, m1) 899 | | mstore(0x40, m2) 900 | | mstore(0x60, m3) 901 | | mstore(0x80, m4) 902 | | mstore(0xa0, m5) 903 | | } 904 | | } 905 | | 906 | | function log(address p0, uint256 p1, address p2) internal pure { 907 | | bytes32 m0; 908 | | bytes32 m1; 909 | | bytes32 m2; 910 | | bytes32 m3; 911 | | /// @solidity memory-safe-assembly 912 | | assembly { 913 | | m0 := mload(0x00) 914 | | m1 := mload(0x20) 915 | | m2 := mload(0x40) 916 | | m3 := mload(0x60) 917 | | // Selector of `log(address,uint256,address)`. 918 | | mstore(0x00, 0x7bc0d848) 919 | | mstore(0x20, p0) 920 | | mstore(0x40, p1) 921 | | mstore(0x60, p2) 922 | | } 923 | | _sendLogPayload(0x1c, 0x64); 924 | | /// @solidity memory-safe-assembly 925 | | assembly { 926 | | mstore(0x00, m0) 927 | | mstore(0x20, m1) 928 | | mstore(0x40, m2) 929 | | mstore(0x60, m3) 930 | | } 931 | | } 932 | | 933 | | function log(address p0, uint256 p1, bool p2) internal pure { 934 | | bytes32 m0; 935 | | bytes32 m1; 936 | | bytes32 m2; 937 | | bytes32 m3; 938 | | /// @solidity memory-safe-assembly 939 | | assembly { 940 | | m0 := mload(0x00) 941 | | m1 := mload(0x20) 942 | | m2 := mload(0x40) 943 | | m3 := mload(0x60) 944 | | // Selector of `log(address,uint256,bool)`. 945 | | mstore(0x00, 0x678209a8) 946 | | mstore(0x20, p0) 947 | | mstore(0x40, p1) 948 | | mstore(0x60, p2) 949 | | } 950 | | _sendLogPayload(0x1c, 0x64); 951 | | /// @solidity memory-safe-assembly 952 | | assembly { 953 | | mstore(0x00, m0) 954 | | mstore(0x20, m1) 955 | | mstore(0x40, m2) 956 | | mstore(0x60, m3) 957 | | } 958 | | } 959 | | 960 | | function log(address p0, uint256 p1, uint256 p2) internal pure { 961 | | bytes32 m0; 962 | | bytes32 m1; 963 | | bytes32 m2; 964 | | bytes32 m3; 965 | | /// @solidity memory-safe-assembly 966 | | assembly { 967 | | m0 := mload(0x00) 968 | | m1 := mload(0x20) 969 | | m2 := mload(0x40) 970 | | m3 := mload(0x60) 971 | | // Selector of `log(address,uint256,uint256)`. 972 | | mstore(0x00, 0xb69bcaf6) 973 | | mstore(0x20, p0) 974 | | mstore(0x40, p1) 975 | | mstore(0x60, p2) 976 | | } 977 | | _sendLogPayload(0x1c, 0x64); 978 | | /// @solidity memory-safe-assembly 979 | | assembly { 980 | | mstore(0x00, m0) 981 | | mstore(0x20, m1) 982 | | mstore(0x40, m2) 983 | | mstore(0x60, m3) 984 | | } 985 | | } 986 | | 987 | | function log(address p0, uint256 p1, bytes32 p2) internal pure { 988 | | bytes32 m0; 989 | | bytes32 m1; 990 | | bytes32 m2; 991 | | bytes32 m3; 992 | | bytes32 m4; 993 | | bytes32 m5; 994 | | /// @solidity memory-safe-assembly 995 | | assembly { 996 | | function writeString(pos, w) { 997 | | let length := 0 998 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 999 | | mstore(pos, length) 1000 | | let shift := sub(256, shl(3, length)) 1001 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1002 | | } 1003 | | m0 := mload(0x00) 1004 | | m1 := mload(0x20) 1005 | | m2 := mload(0x40) 1006 | | m3 := mload(0x60) 1007 | | m4 := mload(0x80) 1008 | | m5 := mload(0xa0) 1009 | | // Selector of `log(address,uint256,string)`. 1010 | | mstore(0x00, 0xa1f2e8aa) 1011 | | mstore(0x20, p0) 1012 | | mstore(0x40, p1) 1013 | | mstore(0x60, 0x60) 1014 | | writeString(0x80, p2) 1015 | | } 1016 | | _sendLogPayload(0x1c, 0xa4); 1017 | | /// @solidity memory-safe-assembly 1018 | | assembly { 1019 | | mstore(0x00, m0) 1020 | | mstore(0x20, m1) 1021 | | mstore(0x40, m2) 1022 | | mstore(0x60, m3) 1023 | | mstore(0x80, m4) 1024 | | mstore(0xa0, m5) 1025 | | } 1026 | | } 1027 | | 1028 | | function log(address p0, bytes32 p1, address p2) internal pure { 1029 | | bytes32 m0; 1030 | | bytes32 m1; 1031 | | bytes32 m2; 1032 | | bytes32 m3; 1033 | | bytes32 m4; 1034 | | bytes32 m5; 1035 | | /// @solidity memory-safe-assembly 1036 | | assembly { 1037 | | function writeString(pos, w) { 1038 | | let length := 0 1039 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1040 | | mstore(pos, length) 1041 | | let shift := sub(256, shl(3, length)) 1042 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1043 | | } 1044 | | m0 := mload(0x00) 1045 | | m1 := mload(0x20) 1046 | | m2 := mload(0x40) 1047 | | m3 := mload(0x60) 1048 | | m4 := mload(0x80) 1049 | | m5 := mload(0xa0) 1050 | | // Selector of `log(address,string,address)`. 1051 | | mstore(0x00, 0xf08744e8) 1052 | | mstore(0x20, p0) 1053 | | mstore(0x40, 0x60) 1054 | | mstore(0x60, p2) 1055 | | writeString(0x80, p1) 1056 | | } 1057 | | _sendLogPayload(0x1c, 0xa4); 1058 | | /// @solidity memory-safe-assembly 1059 | | assembly { 1060 | | mstore(0x00, m0) 1061 | | mstore(0x20, m1) 1062 | | mstore(0x40, m2) 1063 | | mstore(0x60, m3) 1064 | | mstore(0x80, m4) 1065 | | mstore(0xa0, m5) 1066 | | } 1067 | | } 1068 | | 1069 | | function log(address p0, bytes32 p1, bool p2) internal pure { 1070 | | bytes32 m0; 1071 | | bytes32 m1; 1072 | | bytes32 m2; 1073 | | bytes32 m3; 1074 | | bytes32 m4; 1075 | | bytes32 m5; 1076 | | /// @solidity memory-safe-assembly 1077 | | assembly { 1078 | | function writeString(pos, w) { 1079 | | let length := 0 1080 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1081 | | mstore(pos, length) 1082 | | let shift := sub(256, shl(3, length)) 1083 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1084 | | } 1085 | | m0 := mload(0x00) 1086 | | m1 := mload(0x20) 1087 | | m2 := mload(0x40) 1088 | | m3 := mload(0x60) 1089 | | m4 := mload(0x80) 1090 | | m5 := mload(0xa0) 1091 | | // Selector of `log(address,string,bool)`. 1092 | | mstore(0x00, 0xcf020fb1) 1093 | | mstore(0x20, p0) 1094 | | mstore(0x40, 0x60) 1095 | | mstore(0x60, p2) 1096 | | writeString(0x80, p1) 1097 | | } 1098 | | _sendLogPayload(0x1c, 0xa4); 1099 | | /// @solidity memory-safe-assembly 1100 | | assembly { 1101 | | mstore(0x00, m0) 1102 | | mstore(0x20, m1) 1103 | | mstore(0x40, m2) 1104 | | mstore(0x60, m3) 1105 | | mstore(0x80, m4) 1106 | | mstore(0xa0, m5) 1107 | | } 1108 | | } 1109 | | 1110 | | function log(address p0, bytes32 p1, uint256 p2) internal pure { 1111 | | bytes32 m0; 1112 | | bytes32 m1; 1113 | | bytes32 m2; 1114 | | bytes32 m3; 1115 | | bytes32 m4; 1116 | | bytes32 m5; 1117 | | /// @solidity memory-safe-assembly 1118 | | assembly { 1119 | | function writeString(pos, w) { 1120 | | let length := 0 1121 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1122 | | mstore(pos, length) 1123 | | let shift := sub(256, shl(3, length)) 1124 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1125 | | } 1126 | | m0 := mload(0x00) 1127 | | m1 := mload(0x20) 1128 | | m2 := mload(0x40) 1129 | | m3 := mload(0x60) 1130 | | m4 := mload(0x80) 1131 | | m5 := mload(0xa0) 1132 | | // Selector of `log(address,string,uint256)`. 1133 | | mstore(0x00, 0x67dd6ff1) 1134 | | mstore(0x20, p0) 1135 | | mstore(0x40, 0x60) 1136 | | mstore(0x60, p2) 1137 | | writeString(0x80, p1) 1138 | | } 1139 | | _sendLogPayload(0x1c, 0xa4); 1140 | | /// @solidity memory-safe-assembly 1141 | | assembly { 1142 | | mstore(0x00, m0) 1143 | | mstore(0x20, m1) 1144 | | mstore(0x40, m2) 1145 | | mstore(0x60, m3) 1146 | | mstore(0x80, m4) 1147 | | mstore(0xa0, m5) 1148 | | } 1149 | | } 1150 | | 1151 | | function log(address p0, bytes32 p1, bytes32 p2) internal pure { 1152 | | bytes32 m0; 1153 | | bytes32 m1; 1154 | | bytes32 m2; 1155 | | bytes32 m3; 1156 | | bytes32 m4; 1157 | | bytes32 m5; 1158 | | bytes32 m6; 1159 | | bytes32 m7; 1160 | | /// @solidity memory-safe-assembly 1161 | | assembly { 1162 | | function writeString(pos, w) { 1163 | | let length := 0 1164 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1165 | | mstore(pos, length) 1166 | | let shift := sub(256, shl(3, length)) 1167 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1168 | | } 1169 | | m0 := mload(0x00) 1170 | | m1 := mload(0x20) 1171 | | m2 := mload(0x40) 1172 | | m3 := mload(0x60) 1173 | | m4 := mload(0x80) 1174 | | m5 := mload(0xa0) 1175 | | m6 := mload(0xc0) 1176 | | m7 := mload(0xe0) 1177 | | // Selector of `log(address,string,string)`. 1178 | | mstore(0x00, 0xfb772265) 1179 | | mstore(0x20, p0) 1180 | | mstore(0x40, 0x60) 1181 | | mstore(0x60, 0xa0) 1182 | | writeString(0x80, p1) 1183 | | writeString(0xc0, p2) 1184 | | } 1185 | | _sendLogPayload(0x1c, 0xe4); 1186 | | /// @solidity memory-safe-assembly 1187 | | assembly { 1188 | | mstore(0x00, m0) 1189 | | mstore(0x20, m1) 1190 | | mstore(0x40, m2) 1191 | | mstore(0x60, m3) 1192 | | mstore(0x80, m4) 1193 | | mstore(0xa0, m5) 1194 | | mstore(0xc0, m6) 1195 | | mstore(0xe0, m7) 1196 | | } 1197 | | } 1198 | | 1199 | | function log(bool p0, address p1, address p2) internal pure { 1200 | | bytes32 m0; 1201 | | bytes32 m1; 1202 | | bytes32 m2; 1203 | | bytes32 m3; 1204 | | /// @solidity memory-safe-assembly 1205 | | assembly { 1206 | | m0 := mload(0x00) 1207 | | m1 := mload(0x20) 1208 | | m2 := mload(0x40) 1209 | | m3 := mload(0x60) 1210 | | // Selector of `log(bool,address,address)`. 1211 | | mstore(0x00, 0xd2763667) 1212 | | mstore(0x20, p0) 1213 | | mstore(0x40, p1) 1214 | | mstore(0x60, p2) 1215 | | } 1216 | | _sendLogPayload(0x1c, 0x64); 1217 | | /// @solidity memory-safe-assembly 1218 | | assembly { 1219 | | mstore(0x00, m0) 1220 | | mstore(0x20, m1) 1221 | | mstore(0x40, m2) 1222 | | mstore(0x60, m3) 1223 | | } 1224 | | } 1225 | | 1226 | | function log(bool p0, address p1, bool p2) internal pure { 1227 | | bytes32 m0; 1228 | | bytes32 m1; 1229 | | bytes32 m2; 1230 | | bytes32 m3; 1231 | | /// @solidity memory-safe-assembly 1232 | | assembly { 1233 | | m0 := mload(0x00) 1234 | | m1 := mload(0x20) 1235 | | m2 := mload(0x40) 1236 | | m3 := mload(0x60) 1237 | | // Selector of `log(bool,address,bool)`. 1238 | | mstore(0x00, 0x18c9c746) 1239 | | mstore(0x20, p0) 1240 | | mstore(0x40, p1) 1241 | | mstore(0x60, p2) 1242 | | } 1243 | | _sendLogPayload(0x1c, 0x64); 1244 | | /// @solidity memory-safe-assembly 1245 | | assembly { 1246 | | mstore(0x00, m0) 1247 | | mstore(0x20, m1) 1248 | | mstore(0x40, m2) 1249 | | mstore(0x60, m3) 1250 | | } 1251 | | } 1252 | | 1253 | | function log(bool p0, address p1, uint256 p2) internal pure { 1254 | | bytes32 m0; 1255 | | bytes32 m1; 1256 | | bytes32 m2; 1257 | | bytes32 m3; 1258 | | /// @solidity memory-safe-assembly 1259 | | assembly { 1260 | | m0 := mload(0x00) 1261 | | m1 := mload(0x20) 1262 | | m2 := mload(0x40) 1263 | | m3 := mload(0x60) 1264 | | // Selector of `log(bool,address,uint256)`. 1265 | | mstore(0x00, 0x5f7b9afb) 1266 | | mstore(0x20, p0) 1267 | | mstore(0x40, p1) 1268 | | mstore(0x60, p2) 1269 | | } 1270 | | _sendLogPayload(0x1c, 0x64); 1271 | | /// @solidity memory-safe-assembly 1272 | | assembly { 1273 | | mstore(0x00, m0) 1274 | | mstore(0x20, m1) 1275 | | mstore(0x40, m2) 1276 | | mstore(0x60, m3) 1277 | | } 1278 | | } 1279 | | 1280 | | function log(bool p0, address p1, bytes32 p2) internal pure { 1281 | | bytes32 m0; 1282 | | bytes32 m1; 1283 | | bytes32 m2; 1284 | | bytes32 m3; 1285 | | bytes32 m4; 1286 | | bytes32 m5; 1287 | | /// @solidity memory-safe-assembly 1288 | | assembly { 1289 | | function writeString(pos, w) { 1290 | | let length := 0 1291 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1292 | | mstore(pos, length) 1293 | | let shift := sub(256, shl(3, length)) 1294 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1295 | | } 1296 | | m0 := mload(0x00) 1297 | | m1 := mload(0x20) 1298 | | m2 := mload(0x40) 1299 | | m3 := mload(0x60) 1300 | | m4 := mload(0x80) 1301 | | m5 := mload(0xa0) 1302 | | // Selector of `log(bool,address,string)`. 1303 | | mstore(0x00, 0xde9a9270) 1304 | | mstore(0x20, p0) 1305 | | mstore(0x40, p1) 1306 | | mstore(0x60, 0x60) 1307 | | writeString(0x80, p2) 1308 | | } 1309 | | _sendLogPayload(0x1c, 0xa4); 1310 | | /// @solidity memory-safe-assembly 1311 | | assembly { 1312 | | mstore(0x00, m0) 1313 | | mstore(0x20, m1) 1314 | | mstore(0x40, m2) 1315 | | mstore(0x60, m3) 1316 | | mstore(0x80, m4) 1317 | | mstore(0xa0, m5) 1318 | | } 1319 | | } 1320 | | 1321 | | function log(bool p0, bool p1, address p2) internal pure { 1322 | | bytes32 m0; 1323 | | bytes32 m1; 1324 | | bytes32 m2; 1325 | | bytes32 m3; 1326 | | /// @solidity memory-safe-assembly 1327 | | assembly { 1328 | | m0 := mload(0x00) 1329 | | m1 := mload(0x20) 1330 | | m2 := mload(0x40) 1331 | | m3 := mload(0x60) 1332 | | // Selector of `log(bool,bool,address)`. 1333 | | mstore(0x00, 0x1078f68d) 1334 | | mstore(0x20, p0) 1335 | | mstore(0x40, p1) 1336 | | mstore(0x60, p2) 1337 | | } 1338 | | _sendLogPayload(0x1c, 0x64); 1339 | | /// @solidity memory-safe-assembly 1340 | | assembly { 1341 | | mstore(0x00, m0) 1342 | | mstore(0x20, m1) 1343 | | mstore(0x40, m2) 1344 | | mstore(0x60, m3) 1345 | | } 1346 | | } 1347 | | 1348 | | function log(bool p0, bool p1, bool p2) internal pure { 1349 | | bytes32 m0; 1350 | | bytes32 m1; 1351 | | bytes32 m2; 1352 | | bytes32 m3; 1353 | | /// @solidity memory-safe-assembly 1354 | | assembly { 1355 | | m0 := mload(0x00) 1356 | | m1 := mload(0x20) 1357 | | m2 := mload(0x40) 1358 | | m3 := mload(0x60) 1359 | | // Selector of `log(bool,bool,bool)`. 1360 | | mstore(0x00, 0x50709698) 1361 | | mstore(0x20, p0) 1362 | | mstore(0x40, p1) 1363 | | mstore(0x60, p2) 1364 | | } 1365 | | _sendLogPayload(0x1c, 0x64); 1366 | | /// @solidity memory-safe-assembly 1367 | | assembly { 1368 | | mstore(0x00, m0) 1369 | | mstore(0x20, m1) 1370 | | mstore(0x40, m2) 1371 | | mstore(0x60, m3) 1372 | | } 1373 | | } 1374 | | 1375 | | function log(bool p0, bool p1, uint256 p2) internal pure { 1376 | | bytes32 m0; 1377 | | bytes32 m1; 1378 | | bytes32 m2; 1379 | | bytes32 m3; 1380 | | /// @solidity memory-safe-assembly 1381 | | assembly { 1382 | | m0 := mload(0x00) 1383 | | m1 := mload(0x20) 1384 | | m2 := mload(0x40) 1385 | | m3 := mload(0x60) 1386 | | // Selector of `log(bool,bool,uint256)`. 1387 | | mstore(0x00, 0x12f21602) 1388 | | mstore(0x20, p0) 1389 | | mstore(0x40, p1) 1390 | | mstore(0x60, p2) 1391 | | } 1392 | | _sendLogPayload(0x1c, 0x64); 1393 | | /// @solidity memory-safe-assembly 1394 | | assembly { 1395 | | mstore(0x00, m0) 1396 | | mstore(0x20, m1) 1397 | | mstore(0x40, m2) 1398 | | mstore(0x60, m3) 1399 | | } 1400 | | } 1401 | | 1402 | | function log(bool p0, bool p1, bytes32 p2) internal pure { 1403 | | bytes32 m0; 1404 | | bytes32 m1; 1405 | | bytes32 m2; 1406 | | bytes32 m3; 1407 | | bytes32 m4; 1408 | | bytes32 m5; 1409 | | /// @solidity memory-safe-assembly 1410 | | assembly { 1411 | | function writeString(pos, w) { 1412 | | let length := 0 1413 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1414 | | mstore(pos, length) 1415 | | let shift := sub(256, shl(3, length)) 1416 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1417 | | } 1418 | | m0 := mload(0x00) 1419 | | m1 := mload(0x20) 1420 | | m2 := mload(0x40) 1421 | | m3 := mload(0x60) 1422 | | m4 := mload(0x80) 1423 | | m5 := mload(0xa0) 1424 | | // Selector of `log(bool,bool,string)`. 1425 | | mstore(0x00, 0x2555fa46) 1426 | | mstore(0x20, p0) 1427 | | mstore(0x40, p1) 1428 | | mstore(0x60, 0x60) 1429 | | writeString(0x80, p2) 1430 | | } 1431 | | _sendLogPayload(0x1c, 0xa4); 1432 | | /// @solidity memory-safe-assembly 1433 | | assembly { 1434 | | mstore(0x00, m0) 1435 | | mstore(0x20, m1) 1436 | | mstore(0x40, m2) 1437 | | mstore(0x60, m3) 1438 | | mstore(0x80, m4) 1439 | | mstore(0xa0, m5) 1440 | | } 1441 | | } 1442 | | 1443 | | function log(bool p0, uint256 p1, address p2) internal pure { 1444 | | bytes32 m0; 1445 | | bytes32 m1; 1446 | | bytes32 m2; 1447 | | bytes32 m3; 1448 | | /// @solidity memory-safe-assembly 1449 | | assembly { 1450 | | m0 := mload(0x00) 1451 | | m1 := mload(0x20) 1452 | | m2 := mload(0x40) 1453 | | m3 := mload(0x60) 1454 | | // Selector of `log(bool,uint256,address)`. 1455 | | mstore(0x00, 0x088ef9d2) 1456 | | mstore(0x20, p0) 1457 | | mstore(0x40, p1) 1458 | | mstore(0x60, p2) 1459 | | } 1460 | | _sendLogPayload(0x1c, 0x64); 1461 | | /// @solidity memory-safe-assembly 1462 | | assembly { 1463 | | mstore(0x00, m0) 1464 | | mstore(0x20, m1) 1465 | | mstore(0x40, m2) 1466 | | mstore(0x60, m3) 1467 | | } 1468 | | } 1469 | | 1470 | | function log(bool p0, uint256 p1, bool p2) internal pure { 1471 | | bytes32 m0; 1472 | | bytes32 m1; 1473 | | bytes32 m2; 1474 | | bytes32 m3; 1475 | | /// @solidity memory-safe-assembly 1476 | | assembly { 1477 | | m0 := mload(0x00) 1478 | | m1 := mload(0x20) 1479 | | m2 := mload(0x40) 1480 | | m3 := mload(0x60) 1481 | | // Selector of `log(bool,uint256,bool)`. 1482 | | mstore(0x00, 0xe8defba9) 1483 | | mstore(0x20, p0) 1484 | | mstore(0x40, p1) 1485 | | mstore(0x60, p2) 1486 | | } 1487 | | _sendLogPayload(0x1c, 0x64); 1488 | | /// @solidity memory-safe-assembly 1489 | | assembly { 1490 | | mstore(0x00, m0) 1491 | | mstore(0x20, m1) 1492 | | mstore(0x40, m2) 1493 | | mstore(0x60, m3) 1494 | | } 1495 | | } 1496 | | 1497 | | function log(bool p0, uint256 p1, uint256 p2) internal pure { 1498 | | bytes32 m0; 1499 | | bytes32 m1; 1500 | | bytes32 m2; 1501 | | bytes32 m3; 1502 | | /// @solidity memory-safe-assembly 1503 | | assembly { 1504 | | m0 := mload(0x00) 1505 | | m1 := mload(0x20) 1506 | | m2 := mload(0x40) 1507 | | m3 := mload(0x60) 1508 | | // Selector of `log(bool,uint256,uint256)`. 1509 | | mstore(0x00, 0x37103367) 1510 | | mstore(0x20, p0) 1511 | | mstore(0x40, p1) 1512 | | mstore(0x60, p2) 1513 | | } 1514 | | _sendLogPayload(0x1c, 0x64); 1515 | | /// @solidity memory-safe-assembly 1516 | | assembly { 1517 | | mstore(0x00, m0) 1518 | | mstore(0x20, m1) 1519 | | mstore(0x40, m2) 1520 | | mstore(0x60, m3) 1521 | | } 1522 | | } 1523 | | 1524 | | function log(bool p0, uint256 p1, bytes32 p2) internal pure { 1525 | | bytes32 m0; 1526 | | bytes32 m1; 1527 | | bytes32 m2; 1528 | | bytes32 m3; 1529 | | bytes32 m4; 1530 | | bytes32 m5; 1531 | | /// @solidity memory-safe-assembly 1532 | | assembly { 1533 | | function writeString(pos, w) { 1534 | | let length := 0 1535 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1536 | | mstore(pos, length) 1537 | | let shift := sub(256, shl(3, length)) 1538 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1539 | | } 1540 | | m0 := mload(0x00) 1541 | | m1 := mload(0x20) 1542 | | m2 := mload(0x40) 1543 | | m3 := mload(0x60) 1544 | | m4 := mload(0x80) 1545 | | m5 := mload(0xa0) 1546 | | // Selector of `log(bool,uint256,string)`. 1547 | | mstore(0x00, 0xc3fc3970) 1548 | | mstore(0x20, p0) 1549 | | mstore(0x40, p1) 1550 | | mstore(0x60, 0x60) 1551 | | writeString(0x80, p2) 1552 | | } 1553 | | _sendLogPayload(0x1c, 0xa4); 1554 | | /// @solidity memory-safe-assembly 1555 | | assembly { 1556 | | mstore(0x00, m0) 1557 | | mstore(0x20, m1) 1558 | | mstore(0x40, m2) 1559 | | mstore(0x60, m3) 1560 | | mstore(0x80, m4) 1561 | | mstore(0xa0, m5) 1562 | | } 1563 | | } 1564 | | 1565 | | function log(bool p0, bytes32 p1, address p2) internal pure { 1566 | | bytes32 m0; 1567 | | bytes32 m1; 1568 | | bytes32 m2; 1569 | | bytes32 m3; 1570 | | bytes32 m4; 1571 | | bytes32 m5; 1572 | | /// @solidity memory-safe-assembly 1573 | | assembly { 1574 | | function writeString(pos, w) { 1575 | | let length := 0 1576 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1577 | | mstore(pos, length) 1578 | | let shift := sub(256, shl(3, length)) 1579 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1580 | | } 1581 | | m0 := mload(0x00) 1582 | | m1 := mload(0x20) 1583 | | m2 := mload(0x40) 1584 | | m3 := mload(0x60) 1585 | | m4 := mload(0x80) 1586 | | m5 := mload(0xa0) 1587 | | // Selector of `log(bool,string,address)`. 1588 | | mstore(0x00, 0x9591b953) 1589 | | mstore(0x20, p0) 1590 | | mstore(0x40, 0x60) 1591 | | mstore(0x60, p2) 1592 | | writeString(0x80, p1) 1593 | | } 1594 | | _sendLogPayload(0x1c, 0xa4); 1595 | | /// @solidity memory-safe-assembly 1596 | | assembly { 1597 | | mstore(0x00, m0) 1598 | | mstore(0x20, m1) 1599 | | mstore(0x40, m2) 1600 | | mstore(0x60, m3) 1601 | | mstore(0x80, m4) 1602 | | mstore(0xa0, m5) 1603 | | } 1604 | | } 1605 | | 1606 | | function log(bool p0, bytes32 p1, bool p2) internal pure { 1607 | | bytes32 m0; 1608 | | bytes32 m1; 1609 | | bytes32 m2; 1610 | | bytes32 m3; 1611 | | bytes32 m4; 1612 | | bytes32 m5; 1613 | | /// @solidity memory-safe-assembly 1614 | | assembly { 1615 | | function writeString(pos, w) { 1616 | | let length := 0 1617 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1618 | | mstore(pos, length) 1619 | | let shift := sub(256, shl(3, length)) 1620 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1621 | | } 1622 | | m0 := mload(0x00) 1623 | | m1 := mload(0x20) 1624 | | m2 := mload(0x40) 1625 | | m3 := mload(0x60) 1626 | | m4 := mload(0x80) 1627 | | m5 := mload(0xa0) 1628 | | // Selector of `log(bool,string,bool)`. 1629 | | mstore(0x00, 0xdbb4c247) 1630 | | mstore(0x20, p0) 1631 | | mstore(0x40, 0x60) 1632 | | mstore(0x60, p2) 1633 | | writeString(0x80, p1) 1634 | | } 1635 | | _sendLogPayload(0x1c, 0xa4); 1636 | | /// @solidity memory-safe-assembly 1637 | | assembly { 1638 | | mstore(0x00, m0) 1639 | | mstore(0x20, m1) 1640 | | mstore(0x40, m2) 1641 | | mstore(0x60, m3) 1642 | | mstore(0x80, m4) 1643 | | mstore(0xa0, m5) 1644 | | } 1645 | | } 1646 | | 1647 | | function log(bool p0, bytes32 p1, uint256 p2) internal pure { 1648 | | bytes32 m0; 1649 | | bytes32 m1; 1650 | | bytes32 m2; 1651 | | bytes32 m3; 1652 | | bytes32 m4; 1653 | | bytes32 m5; 1654 | | /// @solidity memory-safe-assembly 1655 | | assembly { 1656 | | function writeString(pos, w) { 1657 | | let length := 0 1658 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1659 | | mstore(pos, length) 1660 | | let shift := sub(256, shl(3, length)) 1661 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1662 | | } 1663 | | m0 := mload(0x00) 1664 | | m1 := mload(0x20) 1665 | | m2 := mload(0x40) 1666 | | m3 := mload(0x60) 1667 | | m4 := mload(0x80) 1668 | | m5 := mload(0xa0) 1669 | | // Selector of `log(bool,string,uint256)`. 1670 | | mstore(0x00, 0x1093ee11) 1671 | | mstore(0x20, p0) 1672 | | mstore(0x40, 0x60) 1673 | | mstore(0x60, p2) 1674 | | writeString(0x80, p1) 1675 | | } 1676 | | _sendLogPayload(0x1c, 0xa4); 1677 | | /// @solidity memory-safe-assembly 1678 | | assembly { 1679 | | mstore(0x00, m0) 1680 | | mstore(0x20, m1) 1681 | | mstore(0x40, m2) 1682 | | mstore(0x60, m3) 1683 | | mstore(0x80, m4) 1684 | | mstore(0xa0, m5) 1685 | | } 1686 | | } 1687 | | 1688 | | function log(bool p0, bytes32 p1, bytes32 p2) internal pure { 1689 | | bytes32 m0; 1690 | | bytes32 m1; 1691 | | bytes32 m2; 1692 | | bytes32 m3; 1693 | | bytes32 m4; 1694 | | bytes32 m5; 1695 | | bytes32 m6; 1696 | | bytes32 m7; 1697 | | /// @solidity memory-safe-assembly 1698 | | assembly { 1699 | | function writeString(pos, w) { 1700 | | let length := 0 1701 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1702 | | mstore(pos, length) 1703 | | let shift := sub(256, shl(3, length)) 1704 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1705 | | } 1706 | | m0 := mload(0x00) 1707 | | m1 := mload(0x20) 1708 | | m2 := mload(0x40) 1709 | | m3 := mload(0x60) 1710 | | m4 := mload(0x80) 1711 | | m5 := mload(0xa0) 1712 | | m6 := mload(0xc0) 1713 | | m7 := mload(0xe0) 1714 | | // Selector of `log(bool,string,string)`. 1715 | | mstore(0x00, 0xb076847f) 1716 | | mstore(0x20, p0) 1717 | | mstore(0x40, 0x60) 1718 | | mstore(0x60, 0xa0) 1719 | | writeString(0x80, p1) 1720 | | writeString(0xc0, p2) 1721 | | } 1722 | | _sendLogPayload(0x1c, 0xe4); 1723 | | /// @solidity memory-safe-assembly 1724 | | assembly { 1725 | | mstore(0x00, m0) 1726 | | mstore(0x20, m1) 1727 | | mstore(0x40, m2) 1728 | | mstore(0x60, m3) 1729 | | mstore(0x80, m4) 1730 | | mstore(0xa0, m5) 1731 | | mstore(0xc0, m6) 1732 | | mstore(0xe0, m7) 1733 | | } 1734 | | } 1735 | | 1736 | | function log(uint256 p0, address p1, address p2) internal pure { 1737 | | bytes32 m0; 1738 | | bytes32 m1; 1739 | | bytes32 m2; 1740 | | bytes32 m3; 1741 | | /// @solidity memory-safe-assembly 1742 | | assembly { 1743 | | m0 := mload(0x00) 1744 | | m1 := mload(0x20) 1745 | | m2 := mload(0x40) 1746 | | m3 := mload(0x60) 1747 | | // Selector of `log(uint256,address,address)`. 1748 | | mstore(0x00, 0xbcfd9be0) 1749 | | mstore(0x20, p0) 1750 | | mstore(0x40, p1) 1751 | | mstore(0x60, p2) 1752 | | } 1753 | | _sendLogPayload(0x1c, 0x64); 1754 | | /// @solidity memory-safe-assembly 1755 | | assembly { 1756 | | mstore(0x00, m0) 1757 | | mstore(0x20, m1) 1758 | | mstore(0x40, m2) 1759 | | mstore(0x60, m3) 1760 | | } 1761 | | } 1762 | | 1763 | | function log(uint256 p0, address p1, bool p2) internal pure { 1764 | | bytes32 m0; 1765 | | bytes32 m1; 1766 | | bytes32 m2; 1767 | | bytes32 m3; 1768 | | /// @solidity memory-safe-assembly 1769 | | assembly { 1770 | | m0 := mload(0x00) 1771 | | m1 := mload(0x20) 1772 | | m2 := mload(0x40) 1773 | | m3 := mload(0x60) 1774 | | // Selector of `log(uint256,address,bool)`. 1775 | | mstore(0x00, 0x9b6ec042) 1776 | | mstore(0x20, p0) 1777 | | mstore(0x40, p1) 1778 | | mstore(0x60, p2) 1779 | | } 1780 | | _sendLogPayload(0x1c, 0x64); 1781 | | /// @solidity memory-safe-assembly 1782 | | assembly { 1783 | | mstore(0x00, m0) 1784 | | mstore(0x20, m1) 1785 | | mstore(0x40, m2) 1786 | | mstore(0x60, m3) 1787 | | } 1788 | | } 1789 | | 1790 | | function log(uint256 p0, address p1, uint256 p2) internal pure { 1791 | | bytes32 m0; 1792 | | bytes32 m1; 1793 | | bytes32 m2; 1794 | | bytes32 m3; 1795 | | /// @solidity memory-safe-assembly 1796 | | assembly { 1797 | | m0 := mload(0x00) 1798 | | m1 := mload(0x20) 1799 | | m2 := mload(0x40) 1800 | | m3 := mload(0x60) 1801 | | // Selector of `log(uint256,address,uint256)`. 1802 | | mstore(0x00, 0x5a9b5ed5) 1803 | | mstore(0x20, p0) 1804 | | mstore(0x40, p1) 1805 | | mstore(0x60, p2) 1806 | | } 1807 | | _sendLogPayload(0x1c, 0x64); 1808 | | /// @solidity memory-safe-assembly 1809 | | assembly { 1810 | | mstore(0x00, m0) 1811 | | mstore(0x20, m1) 1812 | | mstore(0x40, m2) 1813 | | mstore(0x60, m3) 1814 | | } 1815 | | } 1816 | | 1817 | | function log(uint256 p0, address p1, bytes32 p2) internal pure { 1818 | | bytes32 m0; 1819 | | bytes32 m1; 1820 | | bytes32 m2; 1821 | | bytes32 m3; 1822 | | bytes32 m4; 1823 | | bytes32 m5; 1824 | | /// @solidity memory-safe-assembly 1825 | | assembly { 1826 | | function writeString(pos, w) { 1827 | | let length := 0 1828 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1829 | | mstore(pos, length) 1830 | | let shift := sub(256, shl(3, length)) 1831 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1832 | | } 1833 | | m0 := mload(0x00) 1834 | | m1 := mload(0x20) 1835 | | m2 := mload(0x40) 1836 | | m3 := mload(0x60) 1837 | | m4 := mload(0x80) 1838 | | m5 := mload(0xa0) 1839 | | // Selector of `log(uint256,address,string)`. 1840 | | mstore(0x00, 0x63cb41f9) 1841 | | mstore(0x20, p0) 1842 | | mstore(0x40, p1) 1843 | | mstore(0x60, 0x60) 1844 | | writeString(0x80, p2) 1845 | | } 1846 | | _sendLogPayload(0x1c, 0xa4); 1847 | | /// @solidity memory-safe-assembly 1848 | | assembly { 1849 | | mstore(0x00, m0) 1850 | | mstore(0x20, m1) 1851 | | mstore(0x40, m2) 1852 | | mstore(0x60, m3) 1853 | | mstore(0x80, m4) 1854 | | mstore(0xa0, m5) 1855 | | } 1856 | | } 1857 | | 1858 | | function log(uint256 p0, bool p1, address p2) internal pure { 1859 | | bytes32 m0; 1860 | | bytes32 m1; 1861 | | bytes32 m2; 1862 | | bytes32 m3; 1863 | | /// @solidity memory-safe-assembly 1864 | | assembly { 1865 | | m0 := mload(0x00) 1866 | | m1 := mload(0x20) 1867 | | m2 := mload(0x40) 1868 | | m3 := mload(0x60) 1869 | | // Selector of `log(uint256,bool,address)`. 1870 | | mstore(0x00, 0x35085f7b) 1871 | | mstore(0x20, p0) 1872 | | mstore(0x40, p1) 1873 | | mstore(0x60, p2) 1874 | | } 1875 | | _sendLogPayload(0x1c, 0x64); 1876 | | /// @solidity memory-safe-assembly 1877 | | assembly { 1878 | | mstore(0x00, m0) 1879 | | mstore(0x20, m1) 1880 | | mstore(0x40, m2) 1881 | | mstore(0x60, m3) 1882 | | } 1883 | | } 1884 | | 1885 | | function log(uint256 p0, bool p1, bool p2) internal pure { 1886 | | bytes32 m0; 1887 | | bytes32 m1; 1888 | | bytes32 m2; 1889 | | bytes32 m3; 1890 | | /// @solidity memory-safe-assembly 1891 | | assembly { 1892 | | m0 := mload(0x00) 1893 | | m1 := mload(0x20) 1894 | | m2 := mload(0x40) 1895 | | m3 := mload(0x60) 1896 | | // Selector of `log(uint256,bool,bool)`. 1897 | | mstore(0x00, 0x20718650) 1898 | | mstore(0x20, p0) 1899 | | mstore(0x40, p1) 1900 | | mstore(0x60, p2) 1901 | | } 1902 | | _sendLogPayload(0x1c, 0x64); 1903 | | /// @solidity memory-safe-assembly 1904 | | assembly { 1905 | | mstore(0x00, m0) 1906 | | mstore(0x20, m1) 1907 | | mstore(0x40, m2) 1908 | | mstore(0x60, m3) 1909 | | } 1910 | | } 1911 | | 1912 | | function log(uint256 p0, bool p1, uint256 p2) internal pure { 1913 | | bytes32 m0; 1914 | | bytes32 m1; 1915 | | bytes32 m2; 1916 | | bytes32 m3; 1917 | | /// @solidity memory-safe-assembly 1918 | | assembly { 1919 | | m0 := mload(0x00) 1920 | | m1 := mload(0x20) 1921 | | m2 := mload(0x40) 1922 | | m3 := mload(0x60) 1923 | | // Selector of `log(uint256,bool,uint256)`. 1924 | | mstore(0x00, 0x20098014) 1925 | | mstore(0x20, p0) 1926 | | mstore(0x40, p1) 1927 | | mstore(0x60, p2) 1928 | | } 1929 | | _sendLogPayload(0x1c, 0x64); 1930 | | /// @solidity memory-safe-assembly 1931 | | assembly { 1932 | | mstore(0x00, m0) 1933 | | mstore(0x20, m1) 1934 | | mstore(0x40, m2) 1935 | | mstore(0x60, m3) 1936 | | } 1937 | | } 1938 | | 1939 | | function log(uint256 p0, bool p1, bytes32 p2) internal pure { 1940 | | bytes32 m0; 1941 | | bytes32 m1; 1942 | | bytes32 m2; 1943 | | bytes32 m3; 1944 | | bytes32 m4; 1945 | | bytes32 m5; 1946 | | /// @solidity memory-safe-assembly 1947 | | assembly { 1948 | | function writeString(pos, w) { 1949 | | let length := 0 1950 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 1951 | | mstore(pos, length) 1952 | | let shift := sub(256, shl(3, length)) 1953 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 1954 | | } 1955 | | m0 := mload(0x00) 1956 | | m1 := mload(0x20) 1957 | | m2 := mload(0x40) 1958 | | m3 := mload(0x60) 1959 | | m4 := mload(0x80) 1960 | | m5 := mload(0xa0) 1961 | | // Selector of `log(uint256,bool,string)`. 1962 | | mstore(0x00, 0x85775021) 1963 | | mstore(0x20, p0) 1964 | | mstore(0x40, p1) 1965 | | mstore(0x60, 0x60) 1966 | | writeString(0x80, p2) 1967 | | } 1968 | | _sendLogPayload(0x1c, 0xa4); 1969 | | /// @solidity memory-safe-assembly 1970 | | assembly { 1971 | | mstore(0x00, m0) 1972 | | mstore(0x20, m1) 1973 | | mstore(0x40, m2) 1974 | | mstore(0x60, m3) 1975 | | mstore(0x80, m4) 1976 | | mstore(0xa0, m5) 1977 | | } 1978 | | } 1979 | | 1980 | | function log(uint256 p0, uint256 p1, address p2) internal pure { 1981 | | bytes32 m0; 1982 | | bytes32 m1; 1983 | | bytes32 m2; 1984 | | bytes32 m3; 1985 | | /// @solidity memory-safe-assembly 1986 | | assembly { 1987 | | m0 := mload(0x00) 1988 | | m1 := mload(0x20) 1989 | | m2 := mload(0x40) 1990 | | m3 := mload(0x60) 1991 | | // Selector of `log(uint256,uint256,address)`. 1992 | | mstore(0x00, 0x5c96b331) 1993 | | mstore(0x20, p0) 1994 | | mstore(0x40, p1) 1995 | | mstore(0x60, p2) 1996 | | } 1997 | | _sendLogPayload(0x1c, 0x64); 1998 | | /// @solidity memory-safe-assembly 1999 | | assembly { 2000 | | mstore(0x00, m0) 2001 | | mstore(0x20, m1) 2002 | | mstore(0x40, m2) 2003 | | mstore(0x60, m3) 2004 | | } 2005 | | } 2006 | | 2007 | | function log(uint256 p0, uint256 p1, bool p2) internal pure { 2008 | | bytes32 m0; 2009 | | bytes32 m1; 2010 | | bytes32 m2; 2011 | | bytes32 m3; 2012 | | /// @solidity memory-safe-assembly 2013 | | assembly { 2014 | | m0 := mload(0x00) 2015 | | m1 := mload(0x20) 2016 | | m2 := mload(0x40) 2017 | | m3 := mload(0x60) 2018 | | // Selector of `log(uint256,uint256,bool)`. 2019 | | mstore(0x00, 0x4766da72) 2020 | | mstore(0x20, p0) 2021 | | mstore(0x40, p1) 2022 | | mstore(0x60, p2) 2023 | | } 2024 | | _sendLogPayload(0x1c, 0x64); 2025 | | /// @solidity memory-safe-assembly 2026 | | assembly { 2027 | | mstore(0x00, m0) 2028 | | mstore(0x20, m1) 2029 | | mstore(0x40, m2) 2030 | | mstore(0x60, m3) 2031 | | } 2032 | | } 2033 | | 2034 | | function log(uint256 p0, uint256 p1, uint256 p2) internal pure { 2035 | | bytes32 m0; 2036 | | bytes32 m1; 2037 | | bytes32 m2; 2038 | | bytes32 m3; 2039 | | /// @solidity memory-safe-assembly 2040 | | assembly { 2041 | | m0 := mload(0x00) 2042 | | m1 := mload(0x20) 2043 | | m2 := mload(0x40) 2044 | | m3 := mload(0x60) 2045 | | // Selector of `log(uint256,uint256,uint256)`. 2046 | | mstore(0x00, 0xd1ed7a3c) 2047 | | mstore(0x20, p0) 2048 | | mstore(0x40, p1) 2049 | | mstore(0x60, p2) 2050 | | } 2051 | | _sendLogPayload(0x1c, 0x64); 2052 | | /// @solidity memory-safe-assembly 2053 | | assembly { 2054 | | mstore(0x00, m0) 2055 | | mstore(0x20, m1) 2056 | | mstore(0x40, m2) 2057 | | mstore(0x60, m3) 2058 | | } 2059 | | } 2060 | | 2061 | | function log(uint256 p0, uint256 p1, bytes32 p2) internal pure { 2062 | | bytes32 m0; 2063 | | bytes32 m1; 2064 | | bytes32 m2; 2065 | | bytes32 m3; 2066 | | bytes32 m4; 2067 | | bytes32 m5; 2068 | | /// @solidity memory-safe-assembly 2069 | | assembly { 2070 | | function writeString(pos, w) { 2071 | | let length := 0 2072 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2073 | | mstore(pos, length) 2074 | | let shift := sub(256, shl(3, length)) 2075 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2076 | | } 2077 | | m0 := mload(0x00) 2078 | | m1 := mload(0x20) 2079 | | m2 := mload(0x40) 2080 | | m3 := mload(0x60) 2081 | | m4 := mload(0x80) 2082 | | m5 := mload(0xa0) 2083 | | // Selector of `log(uint256,uint256,string)`. 2084 | | mstore(0x00, 0x71d04af2) 2085 | | mstore(0x20, p0) 2086 | | mstore(0x40, p1) 2087 | | mstore(0x60, 0x60) 2088 | | writeString(0x80, p2) 2089 | | } 2090 | | _sendLogPayload(0x1c, 0xa4); 2091 | | /// @solidity memory-safe-assembly 2092 | | assembly { 2093 | | mstore(0x00, m0) 2094 | | mstore(0x20, m1) 2095 | | mstore(0x40, m2) 2096 | | mstore(0x60, m3) 2097 | | mstore(0x80, m4) 2098 | | mstore(0xa0, m5) 2099 | | } 2100 | | } 2101 | | 2102 | | function log(uint256 p0, bytes32 p1, address p2) internal pure { 2103 | | bytes32 m0; 2104 | | bytes32 m1; 2105 | | bytes32 m2; 2106 | | bytes32 m3; 2107 | | bytes32 m4; 2108 | | bytes32 m5; 2109 | | /// @solidity memory-safe-assembly 2110 | | assembly { 2111 | | function writeString(pos, w) { 2112 | | let length := 0 2113 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2114 | | mstore(pos, length) 2115 | | let shift := sub(256, shl(3, length)) 2116 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2117 | | } 2118 | | m0 := mload(0x00) 2119 | | m1 := mload(0x20) 2120 | | m2 := mload(0x40) 2121 | | m3 := mload(0x60) 2122 | | m4 := mload(0x80) 2123 | | m5 := mload(0xa0) 2124 | | // Selector of `log(uint256,string,address)`. 2125 | | mstore(0x00, 0x7afac959) 2126 | | mstore(0x20, p0) 2127 | | mstore(0x40, 0x60) 2128 | | mstore(0x60, p2) 2129 | | writeString(0x80, p1) 2130 | | } 2131 | | _sendLogPayload(0x1c, 0xa4); 2132 | | /// @solidity memory-safe-assembly 2133 | | assembly { 2134 | | mstore(0x00, m0) 2135 | | mstore(0x20, m1) 2136 | | mstore(0x40, m2) 2137 | | mstore(0x60, m3) 2138 | | mstore(0x80, m4) 2139 | | mstore(0xa0, m5) 2140 | | } 2141 | | } 2142 | | 2143 | | function log(uint256 p0, bytes32 p1, bool p2) internal pure { 2144 | | bytes32 m0; 2145 | | bytes32 m1; 2146 | | bytes32 m2; 2147 | | bytes32 m3; 2148 | | bytes32 m4; 2149 | | bytes32 m5; 2150 | | /// @solidity memory-safe-assembly 2151 | | assembly { 2152 | | function writeString(pos, w) { 2153 | | let length := 0 2154 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2155 | | mstore(pos, length) 2156 | | let shift := sub(256, shl(3, length)) 2157 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2158 | | } 2159 | | m0 := mload(0x00) 2160 | | m1 := mload(0x20) 2161 | | m2 := mload(0x40) 2162 | | m3 := mload(0x60) 2163 | | m4 := mload(0x80) 2164 | | m5 := mload(0xa0) 2165 | | // Selector of `log(uint256,string,bool)`. 2166 | | mstore(0x00, 0x4ceda75a) 2167 | | mstore(0x20, p0) 2168 | | mstore(0x40, 0x60) 2169 | | mstore(0x60, p2) 2170 | | writeString(0x80, p1) 2171 | | } 2172 | | _sendLogPayload(0x1c, 0xa4); 2173 | | /// @solidity memory-safe-assembly 2174 | | assembly { 2175 | | mstore(0x00, m0) 2176 | | mstore(0x20, m1) 2177 | | mstore(0x40, m2) 2178 | | mstore(0x60, m3) 2179 | | mstore(0x80, m4) 2180 | | mstore(0xa0, m5) 2181 | | } 2182 | | } 2183 | | 2184 | | function log(uint256 p0, bytes32 p1, uint256 p2) internal pure { 2185 | | bytes32 m0; 2186 | | bytes32 m1; 2187 | | bytes32 m2; 2188 | | bytes32 m3; 2189 | | bytes32 m4; 2190 | | bytes32 m5; 2191 | | /// @solidity memory-safe-assembly 2192 | | assembly { 2193 | | function writeString(pos, w) { 2194 | | let length := 0 2195 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2196 | | mstore(pos, length) 2197 | | let shift := sub(256, shl(3, length)) 2198 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2199 | | } 2200 | | m0 := mload(0x00) 2201 | | m1 := mload(0x20) 2202 | | m2 := mload(0x40) 2203 | | m3 := mload(0x60) 2204 | | m4 := mload(0x80) 2205 | | m5 := mload(0xa0) 2206 | | // Selector of `log(uint256,string,uint256)`. 2207 | | mstore(0x00, 0x37aa7d4c) 2208 | | mstore(0x20, p0) 2209 | | mstore(0x40, 0x60) 2210 | | mstore(0x60, p2) 2211 | | writeString(0x80, p1) 2212 | | } 2213 | | _sendLogPayload(0x1c, 0xa4); 2214 | | /// @solidity memory-safe-assembly 2215 | | assembly { 2216 | | mstore(0x00, m0) 2217 | | mstore(0x20, m1) 2218 | | mstore(0x40, m2) 2219 | | mstore(0x60, m3) 2220 | | mstore(0x80, m4) 2221 | | mstore(0xa0, m5) 2222 | | } 2223 | | } 2224 | | 2225 | | function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure { 2226 | | bytes32 m0; 2227 | | bytes32 m1; 2228 | | bytes32 m2; 2229 | | bytes32 m3; 2230 | | bytes32 m4; 2231 | | bytes32 m5; 2232 | | bytes32 m6; 2233 | | bytes32 m7; 2234 | | /// @solidity memory-safe-assembly 2235 | | assembly { 2236 | | function writeString(pos, w) { 2237 | | let length := 0 2238 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2239 | | mstore(pos, length) 2240 | | let shift := sub(256, shl(3, length)) 2241 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2242 | | } 2243 | | m0 := mload(0x00) 2244 | | m1 := mload(0x20) 2245 | | m2 := mload(0x40) 2246 | | m3 := mload(0x60) 2247 | | m4 := mload(0x80) 2248 | | m5 := mload(0xa0) 2249 | | m6 := mload(0xc0) 2250 | | m7 := mload(0xe0) 2251 | | // Selector of `log(uint256,string,string)`. 2252 | | mstore(0x00, 0xb115611f) 2253 | | mstore(0x20, p0) 2254 | | mstore(0x40, 0x60) 2255 | | mstore(0x60, 0xa0) 2256 | | writeString(0x80, p1) 2257 | | writeString(0xc0, p2) 2258 | | } 2259 | | _sendLogPayload(0x1c, 0xe4); 2260 | | /// @solidity memory-safe-assembly 2261 | | assembly { 2262 | | mstore(0x00, m0) 2263 | | mstore(0x20, m1) 2264 | | mstore(0x40, m2) 2265 | | mstore(0x60, m3) 2266 | | mstore(0x80, m4) 2267 | | mstore(0xa0, m5) 2268 | | mstore(0xc0, m6) 2269 | | mstore(0xe0, m7) 2270 | | } 2271 | | } 2272 | | 2273 | | function log(bytes32 p0, address p1, address p2) internal pure { 2274 | | bytes32 m0; 2275 | | bytes32 m1; 2276 | | bytes32 m2; 2277 | | bytes32 m3; 2278 | | bytes32 m4; 2279 | | bytes32 m5; 2280 | | /// @solidity memory-safe-assembly 2281 | | assembly { 2282 | | function writeString(pos, w) { 2283 | | let length := 0 2284 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2285 | | mstore(pos, length) 2286 | | let shift := sub(256, shl(3, length)) 2287 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2288 | | } 2289 | | m0 := mload(0x00) 2290 | | m1 := mload(0x20) 2291 | | m2 := mload(0x40) 2292 | | m3 := mload(0x60) 2293 | | m4 := mload(0x80) 2294 | | m5 := mload(0xa0) 2295 | | // Selector of `log(string,address,address)`. 2296 | | mstore(0x00, 0xfcec75e0) 2297 | | mstore(0x20, 0x60) 2298 | | mstore(0x40, p1) 2299 | | mstore(0x60, p2) 2300 | | writeString(0x80, p0) 2301 | | } 2302 | | _sendLogPayload(0x1c, 0xa4); 2303 | | /// @solidity memory-safe-assembly 2304 | | assembly { 2305 | | mstore(0x00, m0) 2306 | | mstore(0x20, m1) 2307 | | mstore(0x40, m2) 2308 | | mstore(0x60, m3) 2309 | | mstore(0x80, m4) 2310 | | mstore(0xa0, m5) 2311 | | } 2312 | | } 2313 | | 2314 | | function log(bytes32 p0, address p1, bool p2) internal pure { 2315 | | bytes32 m0; 2316 | | bytes32 m1; 2317 | | bytes32 m2; 2318 | | bytes32 m3; 2319 | | bytes32 m4; 2320 | | bytes32 m5; 2321 | | /// @solidity memory-safe-assembly 2322 | | assembly { 2323 | | function writeString(pos, w) { 2324 | | let length := 0 2325 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2326 | | mstore(pos, length) 2327 | | let shift := sub(256, shl(3, length)) 2328 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2329 | | } 2330 | | m0 := mload(0x00) 2331 | | m1 := mload(0x20) 2332 | | m2 := mload(0x40) 2333 | | m3 := mload(0x60) 2334 | | m4 := mload(0x80) 2335 | | m5 := mload(0xa0) 2336 | | // Selector of `log(string,address,bool)`. 2337 | | mstore(0x00, 0xc91d5ed4) 2338 | | mstore(0x20, 0x60) 2339 | | mstore(0x40, p1) 2340 | | mstore(0x60, p2) 2341 | | writeString(0x80, p0) 2342 | | } 2343 | | _sendLogPayload(0x1c, 0xa4); 2344 | | /// @solidity memory-safe-assembly 2345 | | assembly { 2346 | | mstore(0x00, m0) 2347 | | mstore(0x20, m1) 2348 | | mstore(0x40, m2) 2349 | | mstore(0x60, m3) 2350 | | mstore(0x80, m4) 2351 | | mstore(0xa0, m5) 2352 | | } 2353 | | } 2354 | | 2355 | | function log(bytes32 p0, address p1, uint256 p2) internal pure { 2356 | | bytes32 m0; 2357 | | bytes32 m1; 2358 | | bytes32 m2; 2359 | | bytes32 m3; 2360 | | bytes32 m4; 2361 | | bytes32 m5; 2362 | | /// @solidity memory-safe-assembly 2363 | | assembly { 2364 | | function writeString(pos, w) { 2365 | | let length := 0 2366 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2367 | | mstore(pos, length) 2368 | | let shift := sub(256, shl(3, length)) 2369 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2370 | | } 2371 | | m0 := mload(0x00) 2372 | | m1 := mload(0x20) 2373 | | m2 := mload(0x40) 2374 | | m3 := mload(0x60) 2375 | | m4 := mload(0x80) 2376 | | m5 := mload(0xa0) 2377 | | // Selector of `log(string,address,uint256)`. 2378 | | mstore(0x00, 0x0d26b925) 2379 | | mstore(0x20, 0x60) 2380 | | mstore(0x40, p1) 2381 | | mstore(0x60, p2) 2382 | | writeString(0x80, p0) 2383 | | } 2384 | | _sendLogPayload(0x1c, 0xa4); 2385 | | /// @solidity memory-safe-assembly 2386 | | assembly { 2387 | | mstore(0x00, m0) 2388 | | mstore(0x20, m1) 2389 | | mstore(0x40, m2) 2390 | | mstore(0x60, m3) 2391 | | mstore(0x80, m4) 2392 | | mstore(0xa0, m5) 2393 | | } 2394 | | } 2395 | | 2396 | | function log(bytes32 p0, address p1, bytes32 p2) internal pure { 2397 | | bytes32 m0; 2398 | | bytes32 m1; 2399 | | bytes32 m2; 2400 | | bytes32 m3; 2401 | | bytes32 m4; 2402 | | bytes32 m5; 2403 | | bytes32 m6; 2404 | | bytes32 m7; 2405 | | /// @solidity memory-safe-assembly 2406 | | assembly { 2407 | | function writeString(pos, w) { 2408 | | let length := 0 2409 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2410 | | mstore(pos, length) 2411 | | let shift := sub(256, shl(3, length)) 2412 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2413 | | } 2414 | | m0 := mload(0x00) 2415 | | m1 := mload(0x20) 2416 | | m2 := mload(0x40) 2417 | | m3 := mload(0x60) 2418 | | m4 := mload(0x80) 2419 | | m5 := mload(0xa0) 2420 | | m6 := mload(0xc0) 2421 | | m7 := mload(0xe0) 2422 | | // Selector of `log(string,address,string)`. 2423 | | mstore(0x00, 0xe0e9ad4f) 2424 | | mstore(0x20, 0x60) 2425 | | mstore(0x40, p1) 2426 | | mstore(0x60, 0xa0) 2427 | | writeString(0x80, p0) 2428 | | writeString(0xc0, p2) 2429 | | } 2430 | | _sendLogPayload(0x1c, 0xe4); 2431 | | /// @solidity memory-safe-assembly 2432 | | assembly { 2433 | | mstore(0x00, m0) 2434 | | mstore(0x20, m1) 2435 | | mstore(0x40, m2) 2436 | | mstore(0x60, m3) 2437 | | mstore(0x80, m4) 2438 | | mstore(0xa0, m5) 2439 | | mstore(0xc0, m6) 2440 | | mstore(0xe0, m7) 2441 | | } 2442 | | } 2443 | | 2444 | | function log(bytes32 p0, bool p1, address p2) internal pure { 2445 | | bytes32 m0; 2446 | | bytes32 m1; 2447 | | bytes32 m2; 2448 | | bytes32 m3; 2449 | | bytes32 m4; 2450 | | bytes32 m5; 2451 | | /// @solidity memory-safe-assembly 2452 | | assembly { 2453 | | function writeString(pos, w) { 2454 | | let length := 0 2455 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2456 | | mstore(pos, length) 2457 | | let shift := sub(256, shl(3, length)) 2458 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2459 | | } 2460 | | m0 := mload(0x00) 2461 | | m1 := mload(0x20) 2462 | | m2 := mload(0x40) 2463 | | m3 := mload(0x60) 2464 | | m4 := mload(0x80) 2465 | | m5 := mload(0xa0) 2466 | | // Selector of `log(string,bool,address)`. 2467 | | mstore(0x00, 0x932bbb38) 2468 | | mstore(0x20, 0x60) 2469 | | mstore(0x40, p1) 2470 | | mstore(0x60, p2) 2471 | | writeString(0x80, p0) 2472 | | } 2473 | | _sendLogPayload(0x1c, 0xa4); 2474 | | /// @solidity memory-safe-assembly 2475 | | assembly { 2476 | | mstore(0x00, m0) 2477 | | mstore(0x20, m1) 2478 | | mstore(0x40, m2) 2479 | | mstore(0x60, m3) 2480 | | mstore(0x80, m4) 2481 | | mstore(0xa0, m5) 2482 | | } 2483 | | } 2484 | | 2485 | | function log(bytes32 p0, bool p1, bool p2) internal pure { 2486 | | bytes32 m0; 2487 | | bytes32 m1; 2488 | | bytes32 m2; 2489 | | bytes32 m3; 2490 | | bytes32 m4; 2491 | | bytes32 m5; 2492 | | /// @solidity memory-safe-assembly 2493 | | assembly { 2494 | | function writeString(pos, w) { 2495 | | let length := 0 2496 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2497 | | mstore(pos, length) 2498 | | let shift := sub(256, shl(3, length)) 2499 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2500 | | } 2501 | | m0 := mload(0x00) 2502 | | m1 := mload(0x20) 2503 | | m2 := mload(0x40) 2504 | | m3 := mload(0x60) 2505 | | m4 := mload(0x80) 2506 | | m5 := mload(0xa0) 2507 | | // Selector of `log(string,bool,bool)`. 2508 | | mstore(0x00, 0x850b7ad6) 2509 | | mstore(0x20, 0x60) 2510 | | mstore(0x40, p1) 2511 | | mstore(0x60, p2) 2512 | | writeString(0x80, p0) 2513 | | } 2514 | | _sendLogPayload(0x1c, 0xa4); 2515 | | /// @solidity memory-safe-assembly 2516 | | assembly { 2517 | | mstore(0x00, m0) 2518 | | mstore(0x20, m1) 2519 | | mstore(0x40, m2) 2520 | | mstore(0x60, m3) 2521 | | mstore(0x80, m4) 2522 | | mstore(0xa0, m5) 2523 | | } 2524 | | } 2525 | | 2526 | | function log(bytes32 p0, bool p1, uint256 p2) internal pure { 2527 | | bytes32 m0; 2528 | | bytes32 m1; 2529 | | bytes32 m2; 2530 | | bytes32 m3; 2531 | | bytes32 m4; 2532 | | bytes32 m5; 2533 | | /// @solidity memory-safe-assembly 2534 | | assembly { 2535 | | function writeString(pos, w) { 2536 | | let length := 0 2537 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2538 | | mstore(pos, length) 2539 | | let shift := sub(256, shl(3, length)) 2540 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2541 | | } 2542 | | m0 := mload(0x00) 2543 | | m1 := mload(0x20) 2544 | | m2 := mload(0x40) 2545 | | m3 := mload(0x60) 2546 | | m4 := mload(0x80) 2547 | | m5 := mload(0xa0) 2548 | | // Selector of `log(string,bool,uint256)`. 2549 | | mstore(0x00, 0xc95958d6) 2550 | | mstore(0x20, 0x60) 2551 | | mstore(0x40, p1) 2552 | | mstore(0x60, p2) 2553 | | writeString(0x80, p0) 2554 | | } 2555 | | _sendLogPayload(0x1c, 0xa4); 2556 | | /// @solidity memory-safe-assembly 2557 | | assembly { 2558 | | mstore(0x00, m0) 2559 | | mstore(0x20, m1) 2560 | | mstore(0x40, m2) 2561 | | mstore(0x60, m3) 2562 | | mstore(0x80, m4) 2563 | | mstore(0xa0, m5) 2564 | | } 2565 | | } 2566 | | 2567 | | function log(bytes32 p0, bool p1, bytes32 p2) internal pure { 2568 | | bytes32 m0; 2569 | | bytes32 m1; 2570 | | bytes32 m2; 2571 | | bytes32 m3; 2572 | | bytes32 m4; 2573 | | bytes32 m5; 2574 | | bytes32 m6; 2575 | | bytes32 m7; 2576 | | /// @solidity memory-safe-assembly 2577 | | assembly { 2578 | | function writeString(pos, w) { 2579 | | let length := 0 2580 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2581 | | mstore(pos, length) 2582 | | let shift := sub(256, shl(3, length)) 2583 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2584 | | } 2585 | | m0 := mload(0x00) 2586 | | m1 := mload(0x20) 2587 | | m2 := mload(0x40) 2588 | | m3 := mload(0x60) 2589 | | m4 := mload(0x80) 2590 | | m5 := mload(0xa0) 2591 | | m6 := mload(0xc0) 2592 | | m7 := mload(0xe0) 2593 | | // Selector of `log(string,bool,string)`. 2594 | | mstore(0x00, 0xe298f47d) 2595 | | mstore(0x20, 0x60) 2596 | | mstore(0x40, p1) 2597 | | mstore(0x60, 0xa0) 2598 | | writeString(0x80, p0) 2599 | | writeString(0xc0, p2) 2600 | | } 2601 | | _sendLogPayload(0x1c, 0xe4); 2602 | | /// @solidity memory-safe-assembly 2603 | | assembly { 2604 | | mstore(0x00, m0) 2605 | | mstore(0x20, m1) 2606 | | mstore(0x40, m2) 2607 | | mstore(0x60, m3) 2608 | | mstore(0x80, m4) 2609 | | mstore(0xa0, m5) 2610 | | mstore(0xc0, m6) 2611 | | mstore(0xe0, m7) 2612 | | } 2613 | | } 2614 | | 2615 | | function log(bytes32 p0, uint256 p1, address p2) internal pure { 2616 | | bytes32 m0; 2617 | | bytes32 m1; 2618 | | bytes32 m2; 2619 | | bytes32 m3; 2620 | | bytes32 m4; 2621 | | bytes32 m5; 2622 | | /// @solidity memory-safe-assembly 2623 | | assembly { 2624 | | function writeString(pos, w) { 2625 | | let length := 0 2626 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2627 | | mstore(pos, length) 2628 | | let shift := sub(256, shl(3, length)) 2629 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2630 | | } 2631 | | m0 := mload(0x00) 2632 | | m1 := mload(0x20) 2633 | | m2 := mload(0x40) 2634 | | m3 := mload(0x60) 2635 | | m4 := mload(0x80) 2636 | | m5 := mload(0xa0) 2637 | | // Selector of `log(string,uint256,address)`. 2638 | | mstore(0x00, 0x1c7ec448) 2639 | | mstore(0x20, 0x60) 2640 | | mstore(0x40, p1) 2641 | | mstore(0x60, p2) 2642 | | writeString(0x80, p0) 2643 | | } 2644 | | _sendLogPayload(0x1c, 0xa4); 2645 | | /// @solidity memory-safe-assembly 2646 | | assembly { 2647 | | mstore(0x00, m0) 2648 | | mstore(0x20, m1) 2649 | | mstore(0x40, m2) 2650 | | mstore(0x60, m3) 2651 | | mstore(0x80, m4) 2652 | | mstore(0xa0, m5) 2653 | | } 2654 | | } 2655 | | 2656 | | function log(bytes32 p0, uint256 p1, bool p2) internal pure { 2657 | | bytes32 m0; 2658 | | bytes32 m1; 2659 | | bytes32 m2; 2660 | | bytes32 m3; 2661 | | bytes32 m4; 2662 | | bytes32 m5; 2663 | | /// @solidity memory-safe-assembly 2664 | | assembly { 2665 | | function writeString(pos, w) { 2666 | | let length := 0 2667 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2668 | | mstore(pos, length) 2669 | | let shift := sub(256, shl(3, length)) 2670 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2671 | | } 2672 | | m0 := mload(0x00) 2673 | | m1 := mload(0x20) 2674 | | m2 := mload(0x40) 2675 | | m3 := mload(0x60) 2676 | | m4 := mload(0x80) 2677 | | m5 := mload(0xa0) 2678 | | // Selector of `log(string,uint256,bool)`. 2679 | | mstore(0x00, 0xca7733b1) 2680 | | mstore(0x20, 0x60) 2681 | | mstore(0x40, p1) 2682 | | mstore(0x60, p2) 2683 | | writeString(0x80, p0) 2684 | | } 2685 | | _sendLogPayload(0x1c, 0xa4); 2686 | | /// @solidity memory-safe-assembly 2687 | | assembly { 2688 | | mstore(0x00, m0) 2689 | | mstore(0x20, m1) 2690 | | mstore(0x40, m2) 2691 | | mstore(0x60, m3) 2692 | | mstore(0x80, m4) 2693 | | mstore(0xa0, m5) 2694 | | } 2695 | | } 2696 | | 2697 | | function log(bytes32 p0, uint256 p1, uint256 p2) internal pure { 2698 | | bytes32 m0; 2699 | | bytes32 m1; 2700 | | bytes32 m2; 2701 | | bytes32 m3; 2702 | | bytes32 m4; 2703 | | bytes32 m5; 2704 | | /// @solidity memory-safe-assembly 2705 | | assembly { 2706 | | function writeString(pos, w) { 2707 | | let length := 0 2708 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2709 | | mstore(pos, length) 2710 | | let shift := sub(256, shl(3, length)) 2711 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2712 | | } 2713 | | m0 := mload(0x00) 2714 | | m1 := mload(0x20) 2715 | | m2 := mload(0x40) 2716 | | m3 := mload(0x60) 2717 | | m4 := mload(0x80) 2718 | | m5 := mload(0xa0) 2719 | | // Selector of `log(string,uint256,uint256)`. 2720 | | mstore(0x00, 0xca47c4eb) 2721 | | mstore(0x20, 0x60) 2722 | | mstore(0x40, p1) 2723 | | mstore(0x60, p2) 2724 | | writeString(0x80, p0) 2725 | | } 2726 | | _sendLogPayload(0x1c, 0xa4); 2727 | | /// @solidity memory-safe-assembly 2728 | | assembly { 2729 | | mstore(0x00, m0) 2730 | | mstore(0x20, m1) 2731 | | mstore(0x40, m2) 2732 | | mstore(0x60, m3) 2733 | | mstore(0x80, m4) 2734 | | mstore(0xa0, m5) 2735 | | } 2736 | | } 2737 | | 2738 | | function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure { 2739 | | bytes32 m0; 2740 | | bytes32 m1; 2741 | | bytes32 m2; 2742 | | bytes32 m3; 2743 | | bytes32 m4; 2744 | | bytes32 m5; 2745 | | bytes32 m6; 2746 | | bytes32 m7; 2747 | | /// @solidity memory-safe-assembly 2748 | | assembly { 2749 | | function writeString(pos, w) { 2750 | | let length := 0 2751 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2752 | | mstore(pos, length) 2753 | | let shift := sub(256, shl(3, length)) 2754 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2755 | | } 2756 | | m0 := mload(0x00) 2757 | | m1 := mload(0x20) 2758 | | m2 := mload(0x40) 2759 | | m3 := mload(0x60) 2760 | | m4 := mload(0x80) 2761 | | m5 := mload(0xa0) 2762 | | m6 := mload(0xc0) 2763 | | m7 := mload(0xe0) 2764 | | // Selector of `log(string,uint256,string)`. 2765 | | mstore(0x00, 0x5970e089) 2766 | | mstore(0x20, 0x60) 2767 | | mstore(0x40, p1) 2768 | | mstore(0x60, 0xa0) 2769 | | writeString(0x80, p0) 2770 | | writeString(0xc0, p2) 2771 | | } 2772 | | _sendLogPayload(0x1c, 0xe4); 2773 | | /// @solidity memory-safe-assembly 2774 | | assembly { 2775 | | mstore(0x00, m0) 2776 | | mstore(0x20, m1) 2777 | | mstore(0x40, m2) 2778 | | mstore(0x60, m3) 2779 | | mstore(0x80, m4) 2780 | | mstore(0xa0, m5) 2781 | | mstore(0xc0, m6) 2782 | | mstore(0xe0, m7) 2783 | | } 2784 | | } 2785 | | 2786 | | function log(bytes32 p0, bytes32 p1, address p2) internal pure { 2787 | | bytes32 m0; 2788 | | bytes32 m1; 2789 | | bytes32 m2; 2790 | | bytes32 m3; 2791 | | bytes32 m4; 2792 | | bytes32 m5; 2793 | | bytes32 m6; 2794 | | bytes32 m7; 2795 | | /// @solidity memory-safe-assembly 2796 | | assembly { 2797 | | function writeString(pos, w) { 2798 | | let length := 0 2799 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2800 | | mstore(pos, length) 2801 | | let shift := sub(256, shl(3, length)) 2802 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2803 | | } 2804 | | m0 := mload(0x00) 2805 | | m1 := mload(0x20) 2806 | | m2 := mload(0x40) 2807 | | m3 := mload(0x60) 2808 | | m4 := mload(0x80) 2809 | | m5 := mload(0xa0) 2810 | | m6 := mload(0xc0) 2811 | | m7 := mload(0xe0) 2812 | | // Selector of `log(string,string,address)`. 2813 | | mstore(0x00, 0x95ed0195) 2814 | | mstore(0x20, 0x60) 2815 | | mstore(0x40, 0xa0) 2816 | | mstore(0x60, p2) 2817 | | writeString(0x80, p0) 2818 | | writeString(0xc0, p1) 2819 | | } 2820 | | _sendLogPayload(0x1c, 0xe4); 2821 | | /// @solidity memory-safe-assembly 2822 | | assembly { 2823 | | mstore(0x00, m0) 2824 | | mstore(0x20, m1) 2825 | | mstore(0x40, m2) 2826 | | mstore(0x60, m3) 2827 | | mstore(0x80, m4) 2828 | | mstore(0xa0, m5) 2829 | | mstore(0xc0, m6) 2830 | | mstore(0xe0, m7) 2831 | | } 2832 | | } 2833 | | 2834 | | function log(bytes32 p0, bytes32 p1, bool p2) internal pure { 2835 | | bytes32 m0; 2836 | | bytes32 m1; 2837 | | bytes32 m2; 2838 | | bytes32 m3; 2839 | | bytes32 m4; 2840 | | bytes32 m5; 2841 | | bytes32 m6; 2842 | | bytes32 m7; 2843 | | /// @solidity memory-safe-assembly 2844 | | assembly { 2845 | | function writeString(pos, w) { 2846 | | let length := 0 2847 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2848 | | mstore(pos, length) 2849 | | let shift := sub(256, shl(3, length)) 2850 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2851 | | } 2852 | | m0 := mload(0x00) 2853 | | m1 := mload(0x20) 2854 | | m2 := mload(0x40) 2855 | | m3 := mload(0x60) 2856 | | m4 := mload(0x80) 2857 | | m5 := mload(0xa0) 2858 | | m6 := mload(0xc0) 2859 | | m7 := mload(0xe0) 2860 | | // Selector of `log(string,string,bool)`. 2861 | | mstore(0x00, 0xb0e0f9b5) 2862 | | mstore(0x20, 0x60) 2863 | | mstore(0x40, 0xa0) 2864 | | mstore(0x60, p2) 2865 | | writeString(0x80, p0) 2866 | | writeString(0xc0, p1) 2867 | | } 2868 | | _sendLogPayload(0x1c, 0xe4); 2869 | | /// @solidity memory-safe-assembly 2870 | | assembly { 2871 | | mstore(0x00, m0) 2872 | | mstore(0x20, m1) 2873 | | mstore(0x40, m2) 2874 | | mstore(0x60, m3) 2875 | | mstore(0x80, m4) 2876 | | mstore(0xa0, m5) 2877 | | mstore(0xc0, m6) 2878 | | mstore(0xe0, m7) 2879 | | } 2880 | | } 2881 | | 2882 | | function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure { 2883 | | bytes32 m0; 2884 | | bytes32 m1; 2885 | | bytes32 m2; 2886 | | bytes32 m3; 2887 | | bytes32 m4; 2888 | | bytes32 m5; 2889 | | bytes32 m6; 2890 | | bytes32 m7; 2891 | | /// @solidity memory-safe-assembly 2892 | | assembly { 2893 | | function writeString(pos, w) { 2894 | | let length := 0 2895 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2896 | | mstore(pos, length) 2897 | | let shift := sub(256, shl(3, length)) 2898 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2899 | | } 2900 | | m0 := mload(0x00) 2901 | | m1 := mload(0x20) 2902 | | m2 := mload(0x40) 2903 | | m3 := mload(0x60) 2904 | | m4 := mload(0x80) 2905 | | m5 := mload(0xa0) 2906 | | m6 := mload(0xc0) 2907 | | m7 := mload(0xe0) 2908 | | // Selector of `log(string,string,uint256)`. 2909 | | mstore(0x00, 0x5821efa1) 2910 | | mstore(0x20, 0x60) 2911 | | mstore(0x40, 0xa0) 2912 | | mstore(0x60, p2) 2913 | | writeString(0x80, p0) 2914 | | writeString(0xc0, p1) 2915 | | } 2916 | | _sendLogPayload(0x1c, 0xe4); 2917 | | /// @solidity memory-safe-assembly 2918 | | assembly { 2919 | | mstore(0x00, m0) 2920 | | mstore(0x20, m1) 2921 | | mstore(0x40, m2) 2922 | | mstore(0x60, m3) 2923 | | mstore(0x80, m4) 2924 | | mstore(0xa0, m5) 2925 | | mstore(0xc0, m6) 2926 | | mstore(0xe0, m7) 2927 | | } 2928 | | } 2929 | | 2930 | | function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure { 2931 | | bytes32 m0; 2932 | | bytes32 m1; 2933 | | bytes32 m2; 2934 | | bytes32 m3; 2935 | | bytes32 m4; 2936 | | bytes32 m5; 2937 | | bytes32 m6; 2938 | | bytes32 m7; 2939 | | bytes32 m8; 2940 | | bytes32 m9; 2941 | | /// @solidity memory-safe-assembly 2942 | | assembly { 2943 | | function writeString(pos, w) { 2944 | | let length := 0 2945 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 2946 | | mstore(pos, length) 2947 | | let shift := sub(256, shl(3, length)) 2948 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 2949 | | } 2950 | | m0 := mload(0x00) 2951 | | m1 := mload(0x20) 2952 | | m2 := mload(0x40) 2953 | | m3 := mload(0x60) 2954 | | m4 := mload(0x80) 2955 | | m5 := mload(0xa0) 2956 | | m6 := mload(0xc0) 2957 | | m7 := mload(0xe0) 2958 | | m8 := mload(0x100) 2959 | | m9 := mload(0x120) 2960 | | // Selector of `log(string,string,string)`. 2961 | | mstore(0x00, 0x2ced7cef) 2962 | | mstore(0x20, 0x60) 2963 | | mstore(0x40, 0xa0) 2964 | | mstore(0x60, 0xe0) 2965 | | writeString(0x80, p0) 2966 | | writeString(0xc0, p1) 2967 | | writeString(0x100, p2) 2968 | | } 2969 | | _sendLogPayload(0x1c, 0x124); 2970 | | /// @solidity memory-safe-assembly 2971 | | assembly { 2972 | | mstore(0x00, m0) 2973 | | mstore(0x20, m1) 2974 | | mstore(0x40, m2) 2975 | | mstore(0x60, m3) 2976 | | mstore(0x80, m4) 2977 | | mstore(0xa0, m5) 2978 | | mstore(0xc0, m6) 2979 | | mstore(0xe0, m7) 2980 | | mstore(0x100, m8) 2981 | | mstore(0x120, m9) 2982 | | } 2983 | | } 2984 | | 2985 | | function log(address p0, address p1, address p2, address p3) internal pure { 2986 | | bytes32 m0; 2987 | | bytes32 m1; 2988 | | bytes32 m2; 2989 | | bytes32 m3; 2990 | | bytes32 m4; 2991 | | /// @solidity memory-safe-assembly 2992 | | assembly { 2993 | | m0 := mload(0x00) 2994 | | m1 := mload(0x20) 2995 | | m2 := mload(0x40) 2996 | | m3 := mload(0x60) 2997 | | m4 := mload(0x80) 2998 | | // Selector of `log(address,address,address,address)`. 2999 | | mstore(0x00, 0x665bf134) 3000 | | mstore(0x20, p0) 3001 | | mstore(0x40, p1) 3002 | | mstore(0x60, p2) 3003 | | mstore(0x80, p3) 3004 | | } 3005 | | _sendLogPayload(0x1c, 0x84); 3006 | | /// @solidity memory-safe-assembly 3007 | | assembly { 3008 | | mstore(0x00, m0) 3009 | | mstore(0x20, m1) 3010 | | mstore(0x40, m2) 3011 | | mstore(0x60, m3) 3012 | | mstore(0x80, m4) 3013 | | } 3014 | | } 3015 | | 3016 | | function log(address p0, address p1, address p2, bool p3) internal pure { 3017 | | bytes32 m0; 3018 | | bytes32 m1; 3019 | | bytes32 m2; 3020 | | bytes32 m3; 3021 | | bytes32 m4; 3022 | | /// @solidity memory-safe-assembly 3023 | | assembly { 3024 | | m0 := mload(0x00) 3025 | | m1 := mload(0x20) 3026 | | m2 := mload(0x40) 3027 | | m3 := mload(0x60) 3028 | | m4 := mload(0x80) 3029 | | // Selector of `log(address,address,address,bool)`. 3030 | | mstore(0x00, 0x0e378994) 3031 | | mstore(0x20, p0) 3032 | | mstore(0x40, p1) 3033 | | mstore(0x60, p2) 3034 | | mstore(0x80, p3) 3035 | | } 3036 | | _sendLogPayload(0x1c, 0x84); 3037 | | /// @solidity memory-safe-assembly 3038 | | assembly { 3039 | | mstore(0x00, m0) 3040 | | mstore(0x20, m1) 3041 | | mstore(0x40, m2) 3042 | | mstore(0x60, m3) 3043 | | mstore(0x80, m4) 3044 | | } 3045 | | } 3046 | | 3047 | | function log(address p0, address p1, address p2, uint256 p3) internal pure { 3048 | | bytes32 m0; 3049 | | bytes32 m1; 3050 | | bytes32 m2; 3051 | | bytes32 m3; 3052 | | bytes32 m4; 3053 | | /// @solidity memory-safe-assembly 3054 | | assembly { 3055 | | m0 := mload(0x00) 3056 | | m1 := mload(0x20) 3057 | | m2 := mload(0x40) 3058 | | m3 := mload(0x60) 3059 | | m4 := mload(0x80) 3060 | | // Selector of `log(address,address,address,uint256)`. 3061 | | mstore(0x00, 0x94250d77) 3062 | | mstore(0x20, p0) 3063 | | mstore(0x40, p1) 3064 | | mstore(0x60, p2) 3065 | | mstore(0x80, p3) 3066 | | } 3067 | | _sendLogPayload(0x1c, 0x84); 3068 | | /// @solidity memory-safe-assembly 3069 | | assembly { 3070 | | mstore(0x00, m0) 3071 | | mstore(0x20, m1) 3072 | | mstore(0x40, m2) 3073 | | mstore(0x60, m3) 3074 | | mstore(0x80, m4) 3075 | | } 3076 | | } 3077 | | 3078 | | function log(address p0, address p1, address p2, bytes32 p3) internal pure { 3079 | | bytes32 m0; 3080 | | bytes32 m1; 3081 | | bytes32 m2; 3082 | | bytes32 m3; 3083 | | bytes32 m4; 3084 | | bytes32 m5; 3085 | | bytes32 m6; 3086 | | /// @solidity memory-safe-assembly 3087 | | assembly { 3088 | | function writeString(pos, w) { 3089 | | let length := 0 3090 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3091 | | mstore(pos, length) 3092 | | let shift := sub(256, shl(3, length)) 3093 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3094 | | } 3095 | | m0 := mload(0x00) 3096 | | m1 := mload(0x20) 3097 | | m2 := mload(0x40) 3098 | | m3 := mload(0x60) 3099 | | m4 := mload(0x80) 3100 | | m5 := mload(0xa0) 3101 | | m6 := mload(0xc0) 3102 | | // Selector of `log(address,address,address,string)`. 3103 | | mstore(0x00, 0xf808da20) 3104 | | mstore(0x20, p0) 3105 | | mstore(0x40, p1) 3106 | | mstore(0x60, p2) 3107 | | mstore(0x80, 0x80) 3108 | | writeString(0xa0, p3) 3109 | | } 3110 | | _sendLogPayload(0x1c, 0xc4); 3111 | | /// @solidity memory-safe-assembly 3112 | | assembly { 3113 | | mstore(0x00, m0) 3114 | | mstore(0x20, m1) 3115 | | mstore(0x40, m2) 3116 | | mstore(0x60, m3) 3117 | | mstore(0x80, m4) 3118 | | mstore(0xa0, m5) 3119 | | mstore(0xc0, m6) 3120 | | } 3121 | | } 3122 | | 3123 | | function log(address p0, address p1, bool p2, address p3) internal pure { 3124 | | bytes32 m0; 3125 | | bytes32 m1; 3126 | | bytes32 m2; 3127 | | bytes32 m3; 3128 | | bytes32 m4; 3129 | | /// @solidity memory-safe-assembly 3130 | | assembly { 3131 | | m0 := mload(0x00) 3132 | | m1 := mload(0x20) 3133 | | m2 := mload(0x40) 3134 | | m3 := mload(0x60) 3135 | | m4 := mload(0x80) 3136 | | // Selector of `log(address,address,bool,address)`. 3137 | | mstore(0x00, 0x9f1bc36e) 3138 | | mstore(0x20, p0) 3139 | | mstore(0x40, p1) 3140 | | mstore(0x60, p2) 3141 | | mstore(0x80, p3) 3142 | | } 3143 | | _sendLogPayload(0x1c, 0x84); 3144 | | /// @solidity memory-safe-assembly 3145 | | assembly { 3146 | | mstore(0x00, m0) 3147 | | mstore(0x20, m1) 3148 | | mstore(0x40, m2) 3149 | | mstore(0x60, m3) 3150 | | mstore(0x80, m4) 3151 | | } 3152 | | } 3153 | | 3154 | | function log(address p0, address p1, bool p2, bool p3) internal pure { 3155 | | bytes32 m0; 3156 | | bytes32 m1; 3157 | | bytes32 m2; 3158 | | bytes32 m3; 3159 | | bytes32 m4; 3160 | | /// @solidity memory-safe-assembly 3161 | | assembly { 3162 | | m0 := mload(0x00) 3163 | | m1 := mload(0x20) 3164 | | m2 := mload(0x40) 3165 | | m3 := mload(0x60) 3166 | | m4 := mload(0x80) 3167 | | // Selector of `log(address,address,bool,bool)`. 3168 | | mstore(0x00, 0x2cd4134a) 3169 | | mstore(0x20, p0) 3170 | | mstore(0x40, p1) 3171 | | mstore(0x60, p2) 3172 | | mstore(0x80, p3) 3173 | | } 3174 | | _sendLogPayload(0x1c, 0x84); 3175 | | /// @solidity memory-safe-assembly 3176 | | assembly { 3177 | | mstore(0x00, m0) 3178 | | mstore(0x20, m1) 3179 | | mstore(0x40, m2) 3180 | | mstore(0x60, m3) 3181 | | mstore(0x80, m4) 3182 | | } 3183 | | } 3184 | | 3185 | | function log(address p0, address p1, bool p2, uint256 p3) internal pure { 3186 | | bytes32 m0; 3187 | | bytes32 m1; 3188 | | bytes32 m2; 3189 | | bytes32 m3; 3190 | | bytes32 m4; 3191 | | /// @solidity memory-safe-assembly 3192 | | assembly { 3193 | | m0 := mload(0x00) 3194 | | m1 := mload(0x20) 3195 | | m2 := mload(0x40) 3196 | | m3 := mload(0x60) 3197 | | m4 := mload(0x80) 3198 | | // Selector of `log(address,address,bool,uint256)`. 3199 | | mstore(0x00, 0x3971e78c) 3200 | | mstore(0x20, p0) 3201 | | mstore(0x40, p1) 3202 | | mstore(0x60, p2) 3203 | | mstore(0x80, p3) 3204 | | } 3205 | | _sendLogPayload(0x1c, 0x84); 3206 | | /// @solidity memory-safe-assembly 3207 | | assembly { 3208 | | mstore(0x00, m0) 3209 | | mstore(0x20, m1) 3210 | | mstore(0x40, m2) 3211 | | mstore(0x60, m3) 3212 | | mstore(0x80, m4) 3213 | | } 3214 | | } 3215 | | 3216 | | function log(address p0, address p1, bool p2, bytes32 p3) internal pure { 3217 | | bytes32 m0; 3218 | | bytes32 m1; 3219 | | bytes32 m2; 3220 | | bytes32 m3; 3221 | | bytes32 m4; 3222 | | bytes32 m5; 3223 | | bytes32 m6; 3224 | | /// @solidity memory-safe-assembly 3225 | | assembly { 3226 | | function writeString(pos, w) { 3227 | | let length := 0 3228 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3229 | | mstore(pos, length) 3230 | | let shift := sub(256, shl(3, length)) 3231 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3232 | | } 3233 | | m0 := mload(0x00) 3234 | | m1 := mload(0x20) 3235 | | m2 := mload(0x40) 3236 | | m3 := mload(0x60) 3237 | | m4 := mload(0x80) 3238 | | m5 := mload(0xa0) 3239 | | m6 := mload(0xc0) 3240 | | // Selector of `log(address,address,bool,string)`. 3241 | | mstore(0x00, 0xaa6540c8) 3242 | | mstore(0x20, p0) 3243 | | mstore(0x40, p1) 3244 | | mstore(0x60, p2) 3245 | | mstore(0x80, 0x80) 3246 | | writeString(0xa0, p3) 3247 | | } 3248 | | _sendLogPayload(0x1c, 0xc4); 3249 | | /// @solidity memory-safe-assembly 3250 | | assembly { 3251 | | mstore(0x00, m0) 3252 | | mstore(0x20, m1) 3253 | | mstore(0x40, m2) 3254 | | mstore(0x60, m3) 3255 | | mstore(0x80, m4) 3256 | | mstore(0xa0, m5) 3257 | | mstore(0xc0, m6) 3258 | | } 3259 | | } 3260 | | 3261 | | function log(address p0, address p1, uint256 p2, address p3) internal pure { 3262 | | bytes32 m0; 3263 | | bytes32 m1; 3264 | | bytes32 m2; 3265 | | bytes32 m3; 3266 | | bytes32 m4; 3267 | | /// @solidity memory-safe-assembly 3268 | | assembly { 3269 | | m0 := mload(0x00) 3270 | | m1 := mload(0x20) 3271 | | m2 := mload(0x40) 3272 | | m3 := mload(0x60) 3273 | | m4 := mload(0x80) 3274 | | // Selector of `log(address,address,uint256,address)`. 3275 | | mstore(0x00, 0x8da6def5) 3276 | | mstore(0x20, p0) 3277 | | mstore(0x40, p1) 3278 | | mstore(0x60, p2) 3279 | | mstore(0x80, p3) 3280 | | } 3281 | | _sendLogPayload(0x1c, 0x84); 3282 | | /// @solidity memory-safe-assembly 3283 | | assembly { 3284 | | mstore(0x00, m0) 3285 | | mstore(0x20, m1) 3286 | | mstore(0x40, m2) 3287 | | mstore(0x60, m3) 3288 | | mstore(0x80, m4) 3289 | | } 3290 | | } 3291 | | 3292 | | function log(address p0, address p1, uint256 p2, bool p3) internal pure { 3293 | | bytes32 m0; 3294 | | bytes32 m1; 3295 | | bytes32 m2; 3296 | | bytes32 m3; 3297 | | bytes32 m4; 3298 | | /// @solidity memory-safe-assembly 3299 | | assembly { 3300 | | m0 := mload(0x00) 3301 | | m1 := mload(0x20) 3302 | | m2 := mload(0x40) 3303 | | m3 := mload(0x60) 3304 | | m4 := mload(0x80) 3305 | | // Selector of `log(address,address,uint256,bool)`. 3306 | | mstore(0x00, 0x9b4254e2) 3307 | | mstore(0x20, p0) 3308 | | mstore(0x40, p1) 3309 | | mstore(0x60, p2) 3310 | | mstore(0x80, p3) 3311 | | } 3312 | | _sendLogPayload(0x1c, 0x84); 3313 | | /// @solidity memory-safe-assembly 3314 | | assembly { 3315 | | mstore(0x00, m0) 3316 | | mstore(0x20, m1) 3317 | | mstore(0x40, m2) 3318 | | mstore(0x60, m3) 3319 | | mstore(0x80, m4) 3320 | | } 3321 | | } 3322 | | 3323 | | function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { 3324 | | bytes32 m0; 3325 | | bytes32 m1; 3326 | | bytes32 m2; 3327 | | bytes32 m3; 3328 | | bytes32 m4; 3329 | | /// @solidity memory-safe-assembly 3330 | | assembly { 3331 | | m0 := mload(0x00) 3332 | | m1 := mload(0x20) 3333 | | m2 := mload(0x40) 3334 | | m3 := mload(0x60) 3335 | | m4 := mload(0x80) 3336 | | // Selector of `log(address,address,uint256,uint256)`. 3337 | | mstore(0x00, 0xbe553481) 3338 | | mstore(0x20, p0) 3339 | | mstore(0x40, p1) 3340 | | mstore(0x60, p2) 3341 | | mstore(0x80, p3) 3342 | | } 3343 | | _sendLogPayload(0x1c, 0x84); 3344 | | /// @solidity memory-safe-assembly 3345 | | assembly { 3346 | | mstore(0x00, m0) 3347 | | mstore(0x20, m1) 3348 | | mstore(0x40, m2) 3349 | | mstore(0x60, m3) 3350 | | mstore(0x80, m4) 3351 | | } 3352 | | } 3353 | | 3354 | | function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure { 3355 | | bytes32 m0; 3356 | | bytes32 m1; 3357 | | bytes32 m2; 3358 | | bytes32 m3; 3359 | | bytes32 m4; 3360 | | bytes32 m5; 3361 | | bytes32 m6; 3362 | | /// @solidity memory-safe-assembly 3363 | | assembly { 3364 | | function writeString(pos, w) { 3365 | | let length := 0 3366 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3367 | | mstore(pos, length) 3368 | | let shift := sub(256, shl(3, length)) 3369 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3370 | | } 3371 | | m0 := mload(0x00) 3372 | | m1 := mload(0x20) 3373 | | m2 := mload(0x40) 3374 | | m3 := mload(0x60) 3375 | | m4 := mload(0x80) 3376 | | m5 := mload(0xa0) 3377 | | m6 := mload(0xc0) 3378 | | // Selector of `log(address,address,uint256,string)`. 3379 | | mstore(0x00, 0xfdb4f990) 3380 | | mstore(0x20, p0) 3381 | | mstore(0x40, p1) 3382 | | mstore(0x60, p2) 3383 | | mstore(0x80, 0x80) 3384 | | writeString(0xa0, p3) 3385 | | } 3386 | | _sendLogPayload(0x1c, 0xc4); 3387 | | /// @solidity memory-safe-assembly 3388 | | assembly { 3389 | | mstore(0x00, m0) 3390 | | mstore(0x20, m1) 3391 | | mstore(0x40, m2) 3392 | | mstore(0x60, m3) 3393 | | mstore(0x80, m4) 3394 | | mstore(0xa0, m5) 3395 | | mstore(0xc0, m6) 3396 | | } 3397 | | } 3398 | | 3399 | | function log(address p0, address p1, bytes32 p2, address p3) internal pure { 3400 | | bytes32 m0; 3401 | | bytes32 m1; 3402 | | bytes32 m2; 3403 | | bytes32 m3; 3404 | | bytes32 m4; 3405 | | bytes32 m5; 3406 | | bytes32 m6; 3407 | | /// @solidity memory-safe-assembly 3408 | | assembly { 3409 | | function writeString(pos, w) { 3410 | | let length := 0 3411 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3412 | | mstore(pos, length) 3413 | | let shift := sub(256, shl(3, length)) 3414 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3415 | | } 3416 | | m0 := mload(0x00) 3417 | | m1 := mload(0x20) 3418 | | m2 := mload(0x40) 3419 | | m3 := mload(0x60) 3420 | | m4 := mload(0x80) 3421 | | m5 := mload(0xa0) 3422 | | m6 := mload(0xc0) 3423 | | // Selector of `log(address,address,string,address)`. 3424 | | mstore(0x00, 0x8f736d16) 3425 | | mstore(0x20, p0) 3426 | | mstore(0x40, p1) 3427 | | mstore(0x60, 0x80) 3428 | | mstore(0x80, p3) 3429 | | writeString(0xa0, p2) 3430 | | } 3431 | | _sendLogPayload(0x1c, 0xc4); 3432 | | /// @solidity memory-safe-assembly 3433 | | assembly { 3434 | | mstore(0x00, m0) 3435 | | mstore(0x20, m1) 3436 | | mstore(0x40, m2) 3437 | | mstore(0x60, m3) 3438 | | mstore(0x80, m4) 3439 | | mstore(0xa0, m5) 3440 | | mstore(0xc0, m6) 3441 | | } 3442 | | } 3443 | | 3444 | | function log(address p0, address p1, bytes32 p2, bool p3) internal pure { 3445 | | bytes32 m0; 3446 | | bytes32 m1; 3447 | | bytes32 m2; 3448 | | bytes32 m3; 3449 | | bytes32 m4; 3450 | | bytes32 m5; 3451 | | bytes32 m6; 3452 | | /// @solidity memory-safe-assembly 3453 | | assembly { 3454 | | function writeString(pos, w) { 3455 | | let length := 0 3456 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3457 | | mstore(pos, length) 3458 | | let shift := sub(256, shl(3, length)) 3459 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3460 | | } 3461 | | m0 := mload(0x00) 3462 | | m1 := mload(0x20) 3463 | | m2 := mload(0x40) 3464 | | m3 := mload(0x60) 3465 | | m4 := mload(0x80) 3466 | | m5 := mload(0xa0) 3467 | | m6 := mload(0xc0) 3468 | | // Selector of `log(address,address,string,bool)`. 3469 | | mstore(0x00, 0x6f1a594e) 3470 | | mstore(0x20, p0) 3471 | | mstore(0x40, p1) 3472 | | mstore(0x60, 0x80) 3473 | | mstore(0x80, p3) 3474 | | writeString(0xa0, p2) 3475 | | } 3476 | | _sendLogPayload(0x1c, 0xc4); 3477 | | /// @solidity memory-safe-assembly 3478 | | assembly { 3479 | | mstore(0x00, m0) 3480 | | mstore(0x20, m1) 3481 | | mstore(0x40, m2) 3482 | | mstore(0x60, m3) 3483 | | mstore(0x80, m4) 3484 | | mstore(0xa0, m5) 3485 | | mstore(0xc0, m6) 3486 | | } 3487 | | } 3488 | | 3489 | | function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure { 3490 | | bytes32 m0; 3491 | | bytes32 m1; 3492 | | bytes32 m2; 3493 | | bytes32 m3; 3494 | | bytes32 m4; 3495 | | bytes32 m5; 3496 | | bytes32 m6; 3497 | | /// @solidity memory-safe-assembly 3498 | | assembly { 3499 | | function writeString(pos, w) { 3500 | | let length := 0 3501 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3502 | | mstore(pos, length) 3503 | | let shift := sub(256, shl(3, length)) 3504 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3505 | | } 3506 | | m0 := mload(0x00) 3507 | | m1 := mload(0x20) 3508 | | m2 := mload(0x40) 3509 | | m3 := mload(0x60) 3510 | | m4 := mload(0x80) 3511 | | m5 := mload(0xa0) 3512 | | m6 := mload(0xc0) 3513 | | // Selector of `log(address,address,string,uint256)`. 3514 | | mstore(0x00, 0xef1cefe7) 3515 | | mstore(0x20, p0) 3516 | | mstore(0x40, p1) 3517 | | mstore(0x60, 0x80) 3518 | | mstore(0x80, p3) 3519 | | writeString(0xa0, p2) 3520 | | } 3521 | | _sendLogPayload(0x1c, 0xc4); 3522 | | /// @solidity memory-safe-assembly 3523 | | assembly { 3524 | | mstore(0x00, m0) 3525 | | mstore(0x20, m1) 3526 | | mstore(0x40, m2) 3527 | | mstore(0x60, m3) 3528 | | mstore(0x80, m4) 3529 | | mstore(0xa0, m5) 3530 | | mstore(0xc0, m6) 3531 | | } 3532 | | } 3533 | | 3534 | | function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure { 3535 | | bytes32 m0; 3536 | | bytes32 m1; 3537 | | bytes32 m2; 3538 | | bytes32 m3; 3539 | | bytes32 m4; 3540 | | bytes32 m5; 3541 | | bytes32 m6; 3542 | | bytes32 m7; 3543 | | bytes32 m8; 3544 | | /// @solidity memory-safe-assembly 3545 | | assembly { 3546 | | function writeString(pos, w) { 3547 | | let length := 0 3548 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3549 | | mstore(pos, length) 3550 | | let shift := sub(256, shl(3, length)) 3551 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3552 | | } 3553 | | m0 := mload(0x00) 3554 | | m1 := mload(0x20) 3555 | | m2 := mload(0x40) 3556 | | m3 := mload(0x60) 3557 | | m4 := mload(0x80) 3558 | | m5 := mload(0xa0) 3559 | | m6 := mload(0xc0) 3560 | | m7 := mload(0xe0) 3561 | | m8 := mload(0x100) 3562 | | // Selector of `log(address,address,string,string)`. 3563 | | mstore(0x00, 0x21bdaf25) 3564 | | mstore(0x20, p0) 3565 | | mstore(0x40, p1) 3566 | | mstore(0x60, 0x80) 3567 | | mstore(0x80, 0xc0) 3568 | | writeString(0xa0, p2) 3569 | | writeString(0xe0, p3) 3570 | | } 3571 | | _sendLogPayload(0x1c, 0x104); 3572 | | /// @solidity memory-safe-assembly 3573 | | assembly { 3574 | | mstore(0x00, m0) 3575 | | mstore(0x20, m1) 3576 | | mstore(0x40, m2) 3577 | | mstore(0x60, m3) 3578 | | mstore(0x80, m4) 3579 | | mstore(0xa0, m5) 3580 | | mstore(0xc0, m6) 3581 | | mstore(0xe0, m7) 3582 | | mstore(0x100, m8) 3583 | | } 3584 | | } 3585 | | 3586 | | function log(address p0, bool p1, address p2, address p3) internal pure { 3587 | | bytes32 m0; 3588 | | bytes32 m1; 3589 | | bytes32 m2; 3590 | | bytes32 m3; 3591 | | bytes32 m4; 3592 | | /// @solidity memory-safe-assembly 3593 | | assembly { 3594 | | m0 := mload(0x00) 3595 | | m1 := mload(0x20) 3596 | | m2 := mload(0x40) 3597 | | m3 := mload(0x60) 3598 | | m4 := mload(0x80) 3599 | | // Selector of `log(address,bool,address,address)`. 3600 | | mstore(0x00, 0x660375dd) 3601 | | mstore(0x20, p0) 3602 | | mstore(0x40, p1) 3603 | | mstore(0x60, p2) 3604 | | mstore(0x80, p3) 3605 | | } 3606 | | _sendLogPayload(0x1c, 0x84); 3607 | | /// @solidity memory-safe-assembly 3608 | | assembly { 3609 | | mstore(0x00, m0) 3610 | | mstore(0x20, m1) 3611 | | mstore(0x40, m2) 3612 | | mstore(0x60, m3) 3613 | | mstore(0x80, m4) 3614 | | } 3615 | | } 3616 | | 3617 | | function log(address p0, bool p1, address p2, bool p3) internal pure { 3618 | | bytes32 m0; 3619 | | bytes32 m1; 3620 | | bytes32 m2; 3621 | | bytes32 m3; 3622 | | bytes32 m4; 3623 | | /// @solidity memory-safe-assembly 3624 | | assembly { 3625 | | m0 := mload(0x00) 3626 | | m1 := mload(0x20) 3627 | | m2 := mload(0x40) 3628 | | m3 := mload(0x60) 3629 | | m4 := mload(0x80) 3630 | | // Selector of `log(address,bool,address,bool)`. 3631 | | mstore(0x00, 0xa6f50b0f) 3632 | | mstore(0x20, p0) 3633 | | mstore(0x40, p1) 3634 | | mstore(0x60, p2) 3635 | | mstore(0x80, p3) 3636 | | } 3637 | | _sendLogPayload(0x1c, 0x84); 3638 | | /// @solidity memory-safe-assembly 3639 | | assembly { 3640 | | mstore(0x00, m0) 3641 | | mstore(0x20, m1) 3642 | | mstore(0x40, m2) 3643 | | mstore(0x60, m3) 3644 | | mstore(0x80, m4) 3645 | | } 3646 | | } 3647 | | 3648 | | function log(address p0, bool p1, address p2, uint256 p3) internal pure { 3649 | | bytes32 m0; 3650 | | bytes32 m1; 3651 | | bytes32 m2; 3652 | | bytes32 m3; 3653 | | bytes32 m4; 3654 | | /// @solidity memory-safe-assembly 3655 | | assembly { 3656 | | m0 := mload(0x00) 3657 | | m1 := mload(0x20) 3658 | | m2 := mload(0x40) 3659 | | m3 := mload(0x60) 3660 | | m4 := mload(0x80) 3661 | | // Selector of `log(address,bool,address,uint256)`. 3662 | | mstore(0x00, 0xa75c59de) 3663 | | mstore(0x20, p0) 3664 | | mstore(0x40, p1) 3665 | | mstore(0x60, p2) 3666 | | mstore(0x80, p3) 3667 | | } 3668 | | _sendLogPayload(0x1c, 0x84); 3669 | | /// @solidity memory-safe-assembly 3670 | | assembly { 3671 | | mstore(0x00, m0) 3672 | | mstore(0x20, m1) 3673 | | mstore(0x40, m2) 3674 | | mstore(0x60, m3) 3675 | | mstore(0x80, m4) 3676 | | } 3677 | | } 3678 | | 3679 | | function log(address p0, bool p1, address p2, bytes32 p3) internal pure { 3680 | | bytes32 m0; 3681 | | bytes32 m1; 3682 | | bytes32 m2; 3683 | | bytes32 m3; 3684 | | bytes32 m4; 3685 | | bytes32 m5; 3686 | | bytes32 m6; 3687 | | /// @solidity memory-safe-assembly 3688 | | assembly { 3689 | | function writeString(pos, w) { 3690 | | let length := 0 3691 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3692 | | mstore(pos, length) 3693 | | let shift := sub(256, shl(3, length)) 3694 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3695 | | } 3696 | | m0 := mload(0x00) 3697 | | m1 := mload(0x20) 3698 | | m2 := mload(0x40) 3699 | | m3 := mload(0x60) 3700 | | m4 := mload(0x80) 3701 | | m5 := mload(0xa0) 3702 | | m6 := mload(0xc0) 3703 | | // Selector of `log(address,bool,address,string)`. 3704 | | mstore(0x00, 0x2dd778e6) 3705 | | mstore(0x20, p0) 3706 | | mstore(0x40, p1) 3707 | | mstore(0x60, p2) 3708 | | mstore(0x80, 0x80) 3709 | | writeString(0xa0, p3) 3710 | | } 3711 | | _sendLogPayload(0x1c, 0xc4); 3712 | | /// @solidity memory-safe-assembly 3713 | | assembly { 3714 | | mstore(0x00, m0) 3715 | | mstore(0x20, m1) 3716 | | mstore(0x40, m2) 3717 | | mstore(0x60, m3) 3718 | | mstore(0x80, m4) 3719 | | mstore(0xa0, m5) 3720 | | mstore(0xc0, m6) 3721 | | } 3722 | | } 3723 | | 3724 | | function log(address p0, bool p1, bool p2, address p3) internal pure { 3725 | | bytes32 m0; 3726 | | bytes32 m1; 3727 | | bytes32 m2; 3728 | | bytes32 m3; 3729 | | bytes32 m4; 3730 | | /// @solidity memory-safe-assembly 3731 | | assembly { 3732 | | m0 := mload(0x00) 3733 | | m1 := mload(0x20) 3734 | | m2 := mload(0x40) 3735 | | m3 := mload(0x60) 3736 | | m4 := mload(0x80) 3737 | | // Selector of `log(address,bool,bool,address)`. 3738 | | mstore(0x00, 0xcf394485) 3739 | | mstore(0x20, p0) 3740 | | mstore(0x40, p1) 3741 | | mstore(0x60, p2) 3742 | | mstore(0x80, p3) 3743 | | } 3744 | | _sendLogPayload(0x1c, 0x84); 3745 | | /// @solidity memory-safe-assembly 3746 | | assembly { 3747 | | mstore(0x00, m0) 3748 | | mstore(0x20, m1) 3749 | | mstore(0x40, m2) 3750 | | mstore(0x60, m3) 3751 | | mstore(0x80, m4) 3752 | | } 3753 | | } 3754 | | 3755 | | function log(address p0, bool p1, bool p2, bool p3) internal pure { 3756 | | bytes32 m0; 3757 | | bytes32 m1; 3758 | | bytes32 m2; 3759 | | bytes32 m3; 3760 | | bytes32 m4; 3761 | | /// @solidity memory-safe-assembly 3762 | | assembly { 3763 | | m0 := mload(0x00) 3764 | | m1 := mload(0x20) 3765 | | m2 := mload(0x40) 3766 | | m3 := mload(0x60) 3767 | | m4 := mload(0x80) 3768 | | // Selector of `log(address,bool,bool,bool)`. 3769 | | mstore(0x00, 0xcac43479) 3770 | | mstore(0x20, p0) 3771 | | mstore(0x40, p1) 3772 | | mstore(0x60, p2) 3773 | | mstore(0x80, p3) 3774 | | } 3775 | | _sendLogPayload(0x1c, 0x84); 3776 | | /// @solidity memory-safe-assembly 3777 | | assembly { 3778 | | mstore(0x00, m0) 3779 | | mstore(0x20, m1) 3780 | | mstore(0x40, m2) 3781 | | mstore(0x60, m3) 3782 | | mstore(0x80, m4) 3783 | | } 3784 | | } 3785 | | 3786 | | function log(address p0, bool p1, bool p2, uint256 p3) internal pure { 3787 | | bytes32 m0; 3788 | | bytes32 m1; 3789 | | bytes32 m2; 3790 | | bytes32 m3; 3791 | | bytes32 m4; 3792 | | /// @solidity memory-safe-assembly 3793 | | assembly { 3794 | | m0 := mload(0x00) 3795 | | m1 := mload(0x20) 3796 | | m2 := mload(0x40) 3797 | | m3 := mload(0x60) 3798 | | m4 := mload(0x80) 3799 | | // Selector of `log(address,bool,bool,uint256)`. 3800 | | mstore(0x00, 0x8c4e5de6) 3801 | | mstore(0x20, p0) 3802 | | mstore(0x40, p1) 3803 | | mstore(0x60, p2) 3804 | | mstore(0x80, p3) 3805 | | } 3806 | | _sendLogPayload(0x1c, 0x84); 3807 | | /// @solidity memory-safe-assembly 3808 | | assembly { 3809 | | mstore(0x00, m0) 3810 | | mstore(0x20, m1) 3811 | | mstore(0x40, m2) 3812 | | mstore(0x60, m3) 3813 | | mstore(0x80, m4) 3814 | | } 3815 | | } 3816 | | 3817 | | function log(address p0, bool p1, bool p2, bytes32 p3) internal pure { 3818 | | bytes32 m0; 3819 | | bytes32 m1; 3820 | | bytes32 m2; 3821 | | bytes32 m3; 3822 | | bytes32 m4; 3823 | | bytes32 m5; 3824 | | bytes32 m6; 3825 | | /// @solidity memory-safe-assembly 3826 | | assembly { 3827 | | function writeString(pos, w) { 3828 | | let length := 0 3829 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3830 | | mstore(pos, length) 3831 | | let shift := sub(256, shl(3, length)) 3832 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3833 | | } 3834 | | m0 := mload(0x00) 3835 | | m1 := mload(0x20) 3836 | | m2 := mload(0x40) 3837 | | m3 := mload(0x60) 3838 | | m4 := mload(0x80) 3839 | | m5 := mload(0xa0) 3840 | | m6 := mload(0xc0) 3841 | | // Selector of `log(address,bool,bool,string)`. 3842 | | mstore(0x00, 0xdfc4a2e8) 3843 | | mstore(0x20, p0) 3844 | | mstore(0x40, p1) 3845 | | mstore(0x60, p2) 3846 | | mstore(0x80, 0x80) 3847 | | writeString(0xa0, p3) 3848 | | } 3849 | | _sendLogPayload(0x1c, 0xc4); 3850 | | /// @solidity memory-safe-assembly 3851 | | assembly { 3852 | | mstore(0x00, m0) 3853 | | mstore(0x20, m1) 3854 | | mstore(0x40, m2) 3855 | | mstore(0x60, m3) 3856 | | mstore(0x80, m4) 3857 | | mstore(0xa0, m5) 3858 | | mstore(0xc0, m6) 3859 | | } 3860 | | } 3861 | | 3862 | | function log(address p0, bool p1, uint256 p2, address p3) internal pure { 3863 | | bytes32 m0; 3864 | | bytes32 m1; 3865 | | bytes32 m2; 3866 | | bytes32 m3; 3867 | | bytes32 m4; 3868 | | /// @solidity memory-safe-assembly 3869 | | assembly { 3870 | | m0 := mload(0x00) 3871 | | m1 := mload(0x20) 3872 | | m2 := mload(0x40) 3873 | | m3 := mload(0x60) 3874 | | m4 := mload(0x80) 3875 | | // Selector of `log(address,bool,uint256,address)`. 3876 | | mstore(0x00, 0xccf790a1) 3877 | | mstore(0x20, p0) 3878 | | mstore(0x40, p1) 3879 | | mstore(0x60, p2) 3880 | | mstore(0x80, p3) 3881 | | } 3882 | | _sendLogPayload(0x1c, 0x84); 3883 | | /// @solidity memory-safe-assembly 3884 | | assembly { 3885 | | mstore(0x00, m0) 3886 | | mstore(0x20, m1) 3887 | | mstore(0x40, m2) 3888 | | mstore(0x60, m3) 3889 | | mstore(0x80, m4) 3890 | | } 3891 | | } 3892 | | 3893 | | function log(address p0, bool p1, uint256 p2, bool p3) internal pure { 3894 | | bytes32 m0; 3895 | | bytes32 m1; 3896 | | bytes32 m2; 3897 | | bytes32 m3; 3898 | | bytes32 m4; 3899 | | /// @solidity memory-safe-assembly 3900 | | assembly { 3901 | | m0 := mload(0x00) 3902 | | m1 := mload(0x20) 3903 | | m2 := mload(0x40) 3904 | | m3 := mload(0x60) 3905 | | m4 := mload(0x80) 3906 | | // Selector of `log(address,bool,uint256,bool)`. 3907 | | mstore(0x00, 0xc4643e20) 3908 | | mstore(0x20, p0) 3909 | | mstore(0x40, p1) 3910 | | mstore(0x60, p2) 3911 | | mstore(0x80, p3) 3912 | | } 3913 | | _sendLogPayload(0x1c, 0x84); 3914 | | /// @solidity memory-safe-assembly 3915 | | assembly { 3916 | | mstore(0x00, m0) 3917 | | mstore(0x20, m1) 3918 | | mstore(0x40, m2) 3919 | | mstore(0x60, m3) 3920 | | mstore(0x80, m4) 3921 | | } 3922 | | } 3923 | | 3924 | | function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { 3925 | | bytes32 m0; 3926 | | bytes32 m1; 3927 | | bytes32 m2; 3928 | | bytes32 m3; 3929 | | bytes32 m4; 3930 | | /// @solidity memory-safe-assembly 3931 | | assembly { 3932 | | m0 := mload(0x00) 3933 | | m1 := mload(0x20) 3934 | | m2 := mload(0x40) 3935 | | m3 := mload(0x60) 3936 | | m4 := mload(0x80) 3937 | | // Selector of `log(address,bool,uint256,uint256)`. 3938 | | mstore(0x00, 0x386ff5f4) 3939 | | mstore(0x20, p0) 3940 | | mstore(0x40, p1) 3941 | | mstore(0x60, p2) 3942 | | mstore(0x80, p3) 3943 | | } 3944 | | _sendLogPayload(0x1c, 0x84); 3945 | | /// @solidity memory-safe-assembly 3946 | | assembly { 3947 | | mstore(0x00, m0) 3948 | | mstore(0x20, m1) 3949 | | mstore(0x40, m2) 3950 | | mstore(0x60, m3) 3951 | | mstore(0x80, m4) 3952 | | } 3953 | | } 3954 | | 3955 | | function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure { 3956 | | bytes32 m0; 3957 | | bytes32 m1; 3958 | | bytes32 m2; 3959 | | bytes32 m3; 3960 | | bytes32 m4; 3961 | | bytes32 m5; 3962 | | bytes32 m6; 3963 | | /// @solidity memory-safe-assembly 3964 | | assembly { 3965 | | function writeString(pos, w) { 3966 | | let length := 0 3967 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 3968 | | mstore(pos, length) 3969 | | let shift := sub(256, shl(3, length)) 3970 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 3971 | | } 3972 | | m0 := mload(0x00) 3973 | | m1 := mload(0x20) 3974 | | m2 := mload(0x40) 3975 | | m3 := mload(0x60) 3976 | | m4 := mload(0x80) 3977 | | m5 := mload(0xa0) 3978 | | m6 := mload(0xc0) 3979 | | // Selector of `log(address,bool,uint256,string)`. 3980 | | mstore(0x00, 0x0aa6cfad) 3981 | | mstore(0x20, p0) 3982 | | mstore(0x40, p1) 3983 | | mstore(0x60, p2) 3984 | | mstore(0x80, 0x80) 3985 | | writeString(0xa0, p3) 3986 | | } 3987 | | _sendLogPayload(0x1c, 0xc4); 3988 | | /// @solidity memory-safe-assembly 3989 | | assembly { 3990 | | mstore(0x00, m0) 3991 | | mstore(0x20, m1) 3992 | | mstore(0x40, m2) 3993 | | mstore(0x60, m3) 3994 | | mstore(0x80, m4) 3995 | | mstore(0xa0, m5) 3996 | | mstore(0xc0, m6) 3997 | | } 3998 | | } 3999 | | 4000 | | function log(address p0, bool p1, bytes32 p2, address p3) internal pure { 4001 | | bytes32 m0; 4002 | | bytes32 m1; 4003 | | bytes32 m2; 4004 | | bytes32 m3; 4005 | | bytes32 m4; 4006 | | bytes32 m5; 4007 | | bytes32 m6; 4008 | | /// @solidity memory-safe-assembly 4009 | | assembly { 4010 | | function writeString(pos, w) { 4011 | | let length := 0 4012 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4013 | | mstore(pos, length) 4014 | | let shift := sub(256, shl(3, length)) 4015 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4016 | | } 4017 | | m0 := mload(0x00) 4018 | | m1 := mload(0x20) 4019 | | m2 := mload(0x40) 4020 | | m3 := mload(0x60) 4021 | | m4 := mload(0x80) 4022 | | m5 := mload(0xa0) 4023 | | m6 := mload(0xc0) 4024 | | // Selector of `log(address,bool,string,address)`. 4025 | | mstore(0x00, 0x19fd4956) 4026 | | mstore(0x20, p0) 4027 | | mstore(0x40, p1) 4028 | | mstore(0x60, 0x80) 4029 | | mstore(0x80, p3) 4030 | | writeString(0xa0, p2) 4031 | | } 4032 | | _sendLogPayload(0x1c, 0xc4); 4033 | | /// @solidity memory-safe-assembly 4034 | | assembly { 4035 | | mstore(0x00, m0) 4036 | | mstore(0x20, m1) 4037 | | mstore(0x40, m2) 4038 | | mstore(0x60, m3) 4039 | | mstore(0x80, m4) 4040 | | mstore(0xa0, m5) 4041 | | mstore(0xc0, m6) 4042 | | } 4043 | | } 4044 | | 4045 | | function log(address p0, bool p1, bytes32 p2, bool p3) internal pure { 4046 | | bytes32 m0; 4047 | | bytes32 m1; 4048 | | bytes32 m2; 4049 | | bytes32 m3; 4050 | | bytes32 m4; 4051 | | bytes32 m5; 4052 | | bytes32 m6; 4053 | | /// @solidity memory-safe-assembly 4054 | | assembly { 4055 | | function writeString(pos, w) { 4056 | | let length := 0 4057 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4058 | | mstore(pos, length) 4059 | | let shift := sub(256, shl(3, length)) 4060 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4061 | | } 4062 | | m0 := mload(0x00) 4063 | | m1 := mload(0x20) 4064 | | m2 := mload(0x40) 4065 | | m3 := mload(0x60) 4066 | | m4 := mload(0x80) 4067 | | m5 := mload(0xa0) 4068 | | m6 := mload(0xc0) 4069 | | // Selector of `log(address,bool,string,bool)`. 4070 | | mstore(0x00, 0x50ad461d) 4071 | | mstore(0x20, p0) 4072 | | mstore(0x40, p1) 4073 | | mstore(0x60, 0x80) 4074 | | mstore(0x80, p3) 4075 | | writeString(0xa0, p2) 4076 | | } 4077 | | _sendLogPayload(0x1c, 0xc4); 4078 | | /// @solidity memory-safe-assembly 4079 | | assembly { 4080 | | mstore(0x00, m0) 4081 | | mstore(0x20, m1) 4082 | | mstore(0x40, m2) 4083 | | mstore(0x60, m3) 4084 | | mstore(0x80, m4) 4085 | | mstore(0xa0, m5) 4086 | | mstore(0xc0, m6) 4087 | | } 4088 | | } 4089 | | 4090 | | function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure { 4091 | | bytes32 m0; 4092 | | bytes32 m1; 4093 | | bytes32 m2; 4094 | | bytes32 m3; 4095 | | bytes32 m4; 4096 | | bytes32 m5; 4097 | | bytes32 m6; 4098 | | /// @solidity memory-safe-assembly 4099 | | assembly { 4100 | | function writeString(pos, w) { 4101 | | let length := 0 4102 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4103 | | mstore(pos, length) 4104 | | let shift := sub(256, shl(3, length)) 4105 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4106 | | } 4107 | | m0 := mload(0x00) 4108 | | m1 := mload(0x20) 4109 | | m2 := mload(0x40) 4110 | | m3 := mload(0x60) 4111 | | m4 := mload(0x80) 4112 | | m5 := mload(0xa0) 4113 | | m6 := mload(0xc0) 4114 | | // Selector of `log(address,bool,string,uint256)`. 4115 | | mstore(0x00, 0x80e6a20b) 4116 | | mstore(0x20, p0) 4117 | | mstore(0x40, p1) 4118 | | mstore(0x60, 0x80) 4119 | | mstore(0x80, p3) 4120 | | writeString(0xa0, p2) 4121 | | } 4122 | | _sendLogPayload(0x1c, 0xc4); 4123 | | /// @solidity memory-safe-assembly 4124 | | assembly { 4125 | | mstore(0x00, m0) 4126 | | mstore(0x20, m1) 4127 | | mstore(0x40, m2) 4128 | | mstore(0x60, m3) 4129 | | mstore(0x80, m4) 4130 | | mstore(0xa0, m5) 4131 | | mstore(0xc0, m6) 4132 | | } 4133 | | } 4134 | | 4135 | | function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure { 4136 | | bytes32 m0; 4137 | | bytes32 m1; 4138 | | bytes32 m2; 4139 | | bytes32 m3; 4140 | | bytes32 m4; 4141 | | bytes32 m5; 4142 | | bytes32 m6; 4143 | | bytes32 m7; 4144 | | bytes32 m8; 4145 | | /// @solidity memory-safe-assembly 4146 | | assembly { 4147 | | function writeString(pos, w) { 4148 | | let length := 0 4149 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4150 | | mstore(pos, length) 4151 | | let shift := sub(256, shl(3, length)) 4152 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4153 | | } 4154 | | m0 := mload(0x00) 4155 | | m1 := mload(0x20) 4156 | | m2 := mload(0x40) 4157 | | m3 := mload(0x60) 4158 | | m4 := mload(0x80) 4159 | | m5 := mload(0xa0) 4160 | | m6 := mload(0xc0) 4161 | | m7 := mload(0xe0) 4162 | | m8 := mload(0x100) 4163 | | // Selector of `log(address,bool,string,string)`. 4164 | | mstore(0x00, 0x475c5c33) 4165 | | mstore(0x20, p0) 4166 | | mstore(0x40, p1) 4167 | | mstore(0x60, 0x80) 4168 | | mstore(0x80, 0xc0) 4169 | | writeString(0xa0, p2) 4170 | | writeString(0xe0, p3) 4171 | | } 4172 | | _sendLogPayload(0x1c, 0x104); 4173 | | /// @solidity memory-safe-assembly 4174 | | assembly { 4175 | | mstore(0x00, m0) 4176 | | mstore(0x20, m1) 4177 | | mstore(0x40, m2) 4178 | | mstore(0x60, m3) 4179 | | mstore(0x80, m4) 4180 | | mstore(0xa0, m5) 4181 | | mstore(0xc0, m6) 4182 | | mstore(0xe0, m7) 4183 | | mstore(0x100, m8) 4184 | | } 4185 | | } 4186 | | 4187 | | function log(address p0, uint256 p1, address p2, address p3) internal pure { 4188 | | bytes32 m0; 4189 | | bytes32 m1; 4190 | | bytes32 m2; 4191 | | bytes32 m3; 4192 | | bytes32 m4; 4193 | | /// @solidity memory-safe-assembly 4194 | | assembly { 4195 | | m0 := mload(0x00) 4196 | | m1 := mload(0x20) 4197 | | m2 := mload(0x40) 4198 | | m3 := mload(0x60) 4199 | | m4 := mload(0x80) 4200 | | // Selector of `log(address,uint256,address,address)`. 4201 | | mstore(0x00, 0x478d1c62) 4202 | | mstore(0x20, p0) 4203 | | mstore(0x40, p1) 4204 | | mstore(0x60, p2) 4205 | | mstore(0x80, p3) 4206 | | } 4207 | | _sendLogPayload(0x1c, 0x84); 4208 | | /// @solidity memory-safe-assembly 4209 | | assembly { 4210 | | mstore(0x00, m0) 4211 | | mstore(0x20, m1) 4212 | | mstore(0x40, m2) 4213 | | mstore(0x60, m3) 4214 | | mstore(0x80, m4) 4215 | | } 4216 | | } 4217 | | 4218 | | function log(address p0, uint256 p1, address p2, bool p3) internal pure { 4219 | | bytes32 m0; 4220 | | bytes32 m1; 4221 | | bytes32 m2; 4222 | | bytes32 m3; 4223 | | bytes32 m4; 4224 | | /// @solidity memory-safe-assembly 4225 | | assembly { 4226 | | m0 := mload(0x00) 4227 | | m1 := mload(0x20) 4228 | | m2 := mload(0x40) 4229 | | m3 := mload(0x60) 4230 | | m4 := mload(0x80) 4231 | | // Selector of `log(address,uint256,address,bool)`. 4232 | | mstore(0x00, 0xa1bcc9b3) 4233 | | mstore(0x20, p0) 4234 | | mstore(0x40, p1) 4235 | | mstore(0x60, p2) 4236 | | mstore(0x80, p3) 4237 | | } 4238 | | _sendLogPayload(0x1c, 0x84); 4239 | | /// @solidity memory-safe-assembly 4240 | | assembly { 4241 | | mstore(0x00, m0) 4242 | | mstore(0x20, m1) 4243 | | mstore(0x40, m2) 4244 | | mstore(0x60, m3) 4245 | | mstore(0x80, m4) 4246 | | } 4247 | | } 4248 | | 4249 | | function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { 4250 | | bytes32 m0; 4251 | | bytes32 m1; 4252 | | bytes32 m2; 4253 | | bytes32 m3; 4254 | | bytes32 m4; 4255 | | /// @solidity memory-safe-assembly 4256 | | assembly { 4257 | | m0 := mload(0x00) 4258 | | m1 := mload(0x20) 4259 | | m2 := mload(0x40) 4260 | | m3 := mload(0x60) 4261 | | m4 := mload(0x80) 4262 | | // Selector of `log(address,uint256,address,uint256)`. 4263 | | mstore(0x00, 0x100f650e) 4264 | | mstore(0x20, p0) 4265 | | mstore(0x40, p1) 4266 | | mstore(0x60, p2) 4267 | | mstore(0x80, p3) 4268 | | } 4269 | | _sendLogPayload(0x1c, 0x84); 4270 | | /// @solidity memory-safe-assembly 4271 | | assembly { 4272 | | mstore(0x00, m0) 4273 | | mstore(0x20, m1) 4274 | | mstore(0x40, m2) 4275 | | mstore(0x60, m3) 4276 | | mstore(0x80, m4) 4277 | | } 4278 | | } 4279 | | 4280 | | function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure { 4281 | | bytes32 m0; 4282 | | bytes32 m1; 4283 | | bytes32 m2; 4284 | | bytes32 m3; 4285 | | bytes32 m4; 4286 | | bytes32 m5; 4287 | | bytes32 m6; 4288 | | /// @solidity memory-safe-assembly 4289 | | assembly { 4290 | | function writeString(pos, w) { 4291 | | let length := 0 4292 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4293 | | mstore(pos, length) 4294 | | let shift := sub(256, shl(3, length)) 4295 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4296 | | } 4297 | | m0 := mload(0x00) 4298 | | m1 := mload(0x20) 4299 | | m2 := mload(0x40) 4300 | | m3 := mload(0x60) 4301 | | m4 := mload(0x80) 4302 | | m5 := mload(0xa0) 4303 | | m6 := mload(0xc0) 4304 | | // Selector of `log(address,uint256,address,string)`. 4305 | | mstore(0x00, 0x1da986ea) 4306 | | mstore(0x20, p0) 4307 | | mstore(0x40, p1) 4308 | | mstore(0x60, p2) 4309 | | mstore(0x80, 0x80) 4310 | | writeString(0xa0, p3) 4311 | | } 4312 | | _sendLogPayload(0x1c, 0xc4); 4313 | | /// @solidity memory-safe-assembly 4314 | | assembly { 4315 | | mstore(0x00, m0) 4316 | | mstore(0x20, m1) 4317 | | mstore(0x40, m2) 4318 | | mstore(0x60, m3) 4319 | | mstore(0x80, m4) 4320 | | mstore(0xa0, m5) 4321 | | mstore(0xc0, m6) 4322 | | } 4323 | | } 4324 | | 4325 | | function log(address p0, uint256 p1, bool p2, address p3) internal pure { 4326 | | bytes32 m0; 4327 | | bytes32 m1; 4328 | | bytes32 m2; 4329 | | bytes32 m3; 4330 | | bytes32 m4; 4331 | | /// @solidity memory-safe-assembly 4332 | | assembly { 4333 | | m0 := mload(0x00) 4334 | | m1 := mload(0x20) 4335 | | m2 := mload(0x40) 4336 | | m3 := mload(0x60) 4337 | | m4 := mload(0x80) 4338 | | // Selector of `log(address,uint256,bool,address)`. 4339 | | mstore(0x00, 0xa31bfdcc) 4340 | | mstore(0x20, p0) 4341 | | mstore(0x40, p1) 4342 | | mstore(0x60, p2) 4343 | | mstore(0x80, p3) 4344 | | } 4345 | | _sendLogPayload(0x1c, 0x84); 4346 | | /// @solidity memory-safe-assembly 4347 | | assembly { 4348 | | mstore(0x00, m0) 4349 | | mstore(0x20, m1) 4350 | | mstore(0x40, m2) 4351 | | mstore(0x60, m3) 4352 | | mstore(0x80, m4) 4353 | | } 4354 | | } 4355 | | 4356 | | function log(address p0, uint256 p1, bool p2, bool p3) internal pure { 4357 | | bytes32 m0; 4358 | | bytes32 m1; 4359 | | bytes32 m2; 4360 | | bytes32 m3; 4361 | | bytes32 m4; 4362 | | /// @solidity memory-safe-assembly 4363 | | assembly { 4364 | | m0 := mload(0x00) 4365 | | m1 := mload(0x20) 4366 | | m2 := mload(0x40) 4367 | | m3 := mload(0x60) 4368 | | m4 := mload(0x80) 4369 | | // Selector of `log(address,uint256,bool,bool)`. 4370 | | mstore(0x00, 0x3bf5e537) 4371 | | mstore(0x20, p0) 4372 | | mstore(0x40, p1) 4373 | | mstore(0x60, p2) 4374 | | mstore(0x80, p3) 4375 | | } 4376 | | _sendLogPayload(0x1c, 0x84); 4377 | | /// @solidity memory-safe-assembly 4378 | | assembly { 4379 | | mstore(0x00, m0) 4380 | | mstore(0x20, m1) 4381 | | mstore(0x40, m2) 4382 | | mstore(0x60, m3) 4383 | | mstore(0x80, m4) 4384 | | } 4385 | | } 4386 | | 4387 | | function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { 4388 | | bytes32 m0; 4389 | | bytes32 m1; 4390 | | bytes32 m2; 4391 | | bytes32 m3; 4392 | | bytes32 m4; 4393 | | /// @solidity memory-safe-assembly 4394 | | assembly { 4395 | | m0 := mload(0x00) 4396 | | m1 := mload(0x20) 4397 | | m2 := mload(0x40) 4398 | | m3 := mload(0x60) 4399 | | m4 := mload(0x80) 4400 | | // Selector of `log(address,uint256,bool,uint256)`. 4401 | | mstore(0x00, 0x22f6b999) 4402 | | mstore(0x20, p0) 4403 | | mstore(0x40, p1) 4404 | | mstore(0x60, p2) 4405 | | mstore(0x80, p3) 4406 | | } 4407 | | _sendLogPayload(0x1c, 0x84); 4408 | | /// @solidity memory-safe-assembly 4409 | | assembly { 4410 | | mstore(0x00, m0) 4411 | | mstore(0x20, m1) 4412 | | mstore(0x40, m2) 4413 | | mstore(0x60, m3) 4414 | | mstore(0x80, m4) 4415 | | } 4416 | | } 4417 | | 4418 | | function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure { 4419 | | bytes32 m0; 4420 | | bytes32 m1; 4421 | | bytes32 m2; 4422 | | bytes32 m3; 4423 | | bytes32 m4; 4424 | | bytes32 m5; 4425 | | bytes32 m6; 4426 | | /// @solidity memory-safe-assembly 4427 | | assembly { 4428 | | function writeString(pos, w) { 4429 | | let length := 0 4430 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4431 | | mstore(pos, length) 4432 | | let shift := sub(256, shl(3, length)) 4433 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4434 | | } 4435 | | m0 := mload(0x00) 4436 | | m1 := mload(0x20) 4437 | | m2 := mload(0x40) 4438 | | m3 := mload(0x60) 4439 | | m4 := mload(0x80) 4440 | | m5 := mload(0xa0) 4441 | | m6 := mload(0xc0) 4442 | | // Selector of `log(address,uint256,bool,string)`. 4443 | | mstore(0x00, 0xc5ad85f9) 4444 | | mstore(0x20, p0) 4445 | | mstore(0x40, p1) 4446 | | mstore(0x60, p2) 4447 | | mstore(0x80, 0x80) 4448 | | writeString(0xa0, p3) 4449 | | } 4450 | | _sendLogPayload(0x1c, 0xc4); 4451 | | /// @solidity memory-safe-assembly 4452 | | assembly { 4453 | | mstore(0x00, m0) 4454 | | mstore(0x20, m1) 4455 | | mstore(0x40, m2) 4456 | | mstore(0x60, m3) 4457 | | mstore(0x80, m4) 4458 | | mstore(0xa0, m5) 4459 | | mstore(0xc0, m6) 4460 | | } 4461 | | } 4462 | | 4463 | | function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { 4464 | | bytes32 m0; 4465 | | bytes32 m1; 4466 | | bytes32 m2; 4467 | | bytes32 m3; 4468 | | bytes32 m4; 4469 | | /// @solidity memory-safe-assembly 4470 | | assembly { 4471 | | m0 := mload(0x00) 4472 | | m1 := mload(0x20) 4473 | | m2 := mload(0x40) 4474 | | m3 := mload(0x60) 4475 | | m4 := mload(0x80) 4476 | | // Selector of `log(address,uint256,uint256,address)`. 4477 | | mstore(0x00, 0x20e3984d) 4478 | | mstore(0x20, p0) 4479 | | mstore(0x40, p1) 4480 | | mstore(0x60, p2) 4481 | | mstore(0x80, p3) 4482 | | } 4483 | | _sendLogPayload(0x1c, 0x84); 4484 | | /// @solidity memory-safe-assembly 4485 | | assembly { 4486 | | mstore(0x00, m0) 4487 | | mstore(0x20, m1) 4488 | | mstore(0x40, m2) 4489 | | mstore(0x60, m3) 4490 | | mstore(0x80, m4) 4491 | | } 4492 | | } 4493 | | 4494 | | function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { 4495 | | bytes32 m0; 4496 | | bytes32 m1; 4497 | | bytes32 m2; 4498 | | bytes32 m3; 4499 | | bytes32 m4; 4500 | | /// @solidity memory-safe-assembly 4501 | | assembly { 4502 | | m0 := mload(0x00) 4503 | | m1 := mload(0x20) 4504 | | m2 := mload(0x40) 4505 | | m3 := mload(0x60) 4506 | | m4 := mload(0x80) 4507 | | // Selector of `log(address,uint256,uint256,bool)`. 4508 | | mstore(0x00, 0x66f1bc67) 4509 | | mstore(0x20, p0) 4510 | | mstore(0x40, p1) 4511 | | mstore(0x60, p2) 4512 | | mstore(0x80, p3) 4513 | | } 4514 | | _sendLogPayload(0x1c, 0x84); 4515 | | /// @solidity memory-safe-assembly 4516 | | assembly { 4517 | | mstore(0x00, m0) 4518 | | mstore(0x20, m1) 4519 | | mstore(0x40, m2) 4520 | | mstore(0x60, m3) 4521 | | mstore(0x80, m4) 4522 | | } 4523 | | } 4524 | | 4525 | | function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 4526 | | bytes32 m0; 4527 | | bytes32 m1; 4528 | | bytes32 m2; 4529 | | bytes32 m3; 4530 | | bytes32 m4; 4531 | | /// @solidity memory-safe-assembly 4532 | | assembly { 4533 | | m0 := mload(0x00) 4534 | | m1 := mload(0x20) 4535 | | m2 := mload(0x40) 4536 | | m3 := mload(0x60) 4537 | | m4 := mload(0x80) 4538 | | // Selector of `log(address,uint256,uint256,uint256)`. 4539 | | mstore(0x00, 0x34f0e636) 4540 | | mstore(0x20, p0) 4541 | | mstore(0x40, p1) 4542 | | mstore(0x60, p2) 4543 | | mstore(0x80, p3) 4544 | | } 4545 | | _sendLogPayload(0x1c, 0x84); 4546 | | /// @solidity memory-safe-assembly 4547 | | assembly { 4548 | | mstore(0x00, m0) 4549 | | mstore(0x20, m1) 4550 | | mstore(0x40, m2) 4551 | | mstore(0x60, m3) 4552 | | mstore(0x80, m4) 4553 | | } 4554 | | } 4555 | | 4556 | | function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { 4557 | | bytes32 m0; 4558 | | bytes32 m1; 4559 | | bytes32 m2; 4560 | | bytes32 m3; 4561 | | bytes32 m4; 4562 | | bytes32 m5; 4563 | | bytes32 m6; 4564 | | /// @solidity memory-safe-assembly 4565 | | assembly { 4566 | | function writeString(pos, w) { 4567 | | let length := 0 4568 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4569 | | mstore(pos, length) 4570 | | let shift := sub(256, shl(3, length)) 4571 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4572 | | } 4573 | | m0 := mload(0x00) 4574 | | m1 := mload(0x20) 4575 | | m2 := mload(0x40) 4576 | | m3 := mload(0x60) 4577 | | m4 := mload(0x80) 4578 | | m5 := mload(0xa0) 4579 | | m6 := mload(0xc0) 4580 | | // Selector of `log(address,uint256,uint256,string)`. 4581 | | mstore(0x00, 0x4a28c017) 4582 | | mstore(0x20, p0) 4583 | | mstore(0x40, p1) 4584 | | mstore(0x60, p2) 4585 | | mstore(0x80, 0x80) 4586 | | writeString(0xa0, p3) 4587 | | } 4588 | | _sendLogPayload(0x1c, 0xc4); 4589 | | /// @solidity memory-safe-assembly 4590 | | assembly { 4591 | | mstore(0x00, m0) 4592 | | mstore(0x20, m1) 4593 | | mstore(0x40, m2) 4594 | | mstore(0x60, m3) 4595 | | mstore(0x80, m4) 4596 | | mstore(0xa0, m5) 4597 | | mstore(0xc0, m6) 4598 | | } 4599 | | } 4600 | | 4601 | | function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure { 4602 | | bytes32 m0; 4603 | | bytes32 m1; 4604 | | bytes32 m2; 4605 | | bytes32 m3; 4606 | | bytes32 m4; 4607 | | bytes32 m5; 4608 | | bytes32 m6; 4609 | | /// @solidity memory-safe-assembly 4610 | | assembly { 4611 | | function writeString(pos, w) { 4612 | | let length := 0 4613 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4614 | | mstore(pos, length) 4615 | | let shift := sub(256, shl(3, length)) 4616 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4617 | | } 4618 | | m0 := mload(0x00) 4619 | | m1 := mload(0x20) 4620 | | m2 := mload(0x40) 4621 | | m3 := mload(0x60) 4622 | | m4 := mload(0x80) 4623 | | m5 := mload(0xa0) 4624 | | m6 := mload(0xc0) 4625 | | // Selector of `log(address,uint256,string,address)`. 4626 | | mstore(0x00, 0x5c430d47) 4627 | | mstore(0x20, p0) 4628 | | mstore(0x40, p1) 4629 | | mstore(0x60, 0x80) 4630 | | mstore(0x80, p3) 4631 | | writeString(0xa0, p2) 4632 | | } 4633 | | _sendLogPayload(0x1c, 0xc4); 4634 | | /// @solidity memory-safe-assembly 4635 | | assembly { 4636 | | mstore(0x00, m0) 4637 | | mstore(0x20, m1) 4638 | | mstore(0x40, m2) 4639 | | mstore(0x60, m3) 4640 | | mstore(0x80, m4) 4641 | | mstore(0xa0, m5) 4642 | | mstore(0xc0, m6) 4643 | | } 4644 | | } 4645 | | 4646 | | function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure { 4647 | | bytes32 m0; 4648 | | bytes32 m1; 4649 | | bytes32 m2; 4650 | | bytes32 m3; 4651 | | bytes32 m4; 4652 | | bytes32 m5; 4653 | | bytes32 m6; 4654 | | /// @solidity memory-safe-assembly 4655 | | assembly { 4656 | | function writeString(pos, w) { 4657 | | let length := 0 4658 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4659 | | mstore(pos, length) 4660 | | let shift := sub(256, shl(3, length)) 4661 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4662 | | } 4663 | | m0 := mload(0x00) 4664 | | m1 := mload(0x20) 4665 | | m2 := mload(0x40) 4666 | | m3 := mload(0x60) 4667 | | m4 := mload(0x80) 4668 | | m5 := mload(0xa0) 4669 | | m6 := mload(0xc0) 4670 | | // Selector of `log(address,uint256,string,bool)`. 4671 | | mstore(0x00, 0xcf18105c) 4672 | | mstore(0x20, p0) 4673 | | mstore(0x40, p1) 4674 | | mstore(0x60, 0x80) 4675 | | mstore(0x80, p3) 4676 | | writeString(0xa0, p2) 4677 | | } 4678 | | _sendLogPayload(0x1c, 0xc4); 4679 | | /// @solidity memory-safe-assembly 4680 | | assembly { 4681 | | mstore(0x00, m0) 4682 | | mstore(0x20, m1) 4683 | | mstore(0x40, m2) 4684 | | mstore(0x60, m3) 4685 | | mstore(0x80, m4) 4686 | | mstore(0xa0, m5) 4687 | | mstore(0xc0, m6) 4688 | | } 4689 | | } 4690 | | 4691 | | function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { 4692 | | bytes32 m0; 4693 | | bytes32 m1; 4694 | | bytes32 m2; 4695 | | bytes32 m3; 4696 | | bytes32 m4; 4697 | | bytes32 m5; 4698 | | bytes32 m6; 4699 | | /// @solidity memory-safe-assembly 4700 | | assembly { 4701 | | function writeString(pos, w) { 4702 | | let length := 0 4703 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4704 | | mstore(pos, length) 4705 | | let shift := sub(256, shl(3, length)) 4706 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4707 | | } 4708 | | m0 := mload(0x00) 4709 | | m1 := mload(0x20) 4710 | | m2 := mload(0x40) 4711 | | m3 := mload(0x60) 4712 | | m4 := mload(0x80) 4713 | | m5 := mload(0xa0) 4714 | | m6 := mload(0xc0) 4715 | | // Selector of `log(address,uint256,string,uint256)`. 4716 | | mstore(0x00, 0xbf01f891) 4717 | | mstore(0x20, p0) 4718 | | mstore(0x40, p1) 4719 | | mstore(0x60, 0x80) 4720 | | mstore(0x80, p3) 4721 | | writeString(0xa0, p2) 4722 | | } 4723 | | _sendLogPayload(0x1c, 0xc4); 4724 | | /// @solidity memory-safe-assembly 4725 | | assembly { 4726 | | mstore(0x00, m0) 4727 | | mstore(0x20, m1) 4728 | | mstore(0x40, m2) 4729 | | mstore(0x60, m3) 4730 | | mstore(0x80, m4) 4731 | | mstore(0xa0, m5) 4732 | | mstore(0xc0, m6) 4733 | | } 4734 | | } 4735 | | 4736 | | function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { 4737 | | bytes32 m0; 4738 | | bytes32 m1; 4739 | | bytes32 m2; 4740 | | bytes32 m3; 4741 | | bytes32 m4; 4742 | | bytes32 m5; 4743 | | bytes32 m6; 4744 | | bytes32 m7; 4745 | | bytes32 m8; 4746 | | /// @solidity memory-safe-assembly 4747 | | assembly { 4748 | | function writeString(pos, w) { 4749 | | let length := 0 4750 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4751 | | mstore(pos, length) 4752 | | let shift := sub(256, shl(3, length)) 4753 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4754 | | } 4755 | | m0 := mload(0x00) 4756 | | m1 := mload(0x20) 4757 | | m2 := mload(0x40) 4758 | | m3 := mload(0x60) 4759 | | m4 := mload(0x80) 4760 | | m5 := mload(0xa0) 4761 | | m6 := mload(0xc0) 4762 | | m7 := mload(0xe0) 4763 | | m8 := mload(0x100) 4764 | | // Selector of `log(address,uint256,string,string)`. 4765 | | mstore(0x00, 0x88a8c406) 4766 | | mstore(0x20, p0) 4767 | | mstore(0x40, p1) 4768 | | mstore(0x60, 0x80) 4769 | | mstore(0x80, 0xc0) 4770 | | writeString(0xa0, p2) 4771 | | writeString(0xe0, p3) 4772 | | } 4773 | | _sendLogPayload(0x1c, 0x104); 4774 | | /// @solidity memory-safe-assembly 4775 | | assembly { 4776 | | mstore(0x00, m0) 4777 | | mstore(0x20, m1) 4778 | | mstore(0x40, m2) 4779 | | mstore(0x60, m3) 4780 | | mstore(0x80, m4) 4781 | | mstore(0xa0, m5) 4782 | | mstore(0xc0, m6) 4783 | | mstore(0xe0, m7) 4784 | | mstore(0x100, m8) 4785 | | } 4786 | | } 4787 | | 4788 | | function log(address p0, bytes32 p1, address p2, address p3) internal pure { 4789 | | bytes32 m0; 4790 | | bytes32 m1; 4791 | | bytes32 m2; 4792 | | bytes32 m3; 4793 | | bytes32 m4; 4794 | | bytes32 m5; 4795 | | bytes32 m6; 4796 | | /// @solidity memory-safe-assembly 4797 | | assembly { 4798 | | function writeString(pos, w) { 4799 | | let length := 0 4800 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4801 | | mstore(pos, length) 4802 | | let shift := sub(256, shl(3, length)) 4803 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4804 | | } 4805 | | m0 := mload(0x00) 4806 | | m1 := mload(0x20) 4807 | | m2 := mload(0x40) 4808 | | m3 := mload(0x60) 4809 | | m4 := mload(0x80) 4810 | | m5 := mload(0xa0) 4811 | | m6 := mload(0xc0) 4812 | | // Selector of `log(address,string,address,address)`. 4813 | | mstore(0x00, 0x0d36fa20) 4814 | | mstore(0x20, p0) 4815 | | mstore(0x40, 0x80) 4816 | | mstore(0x60, p2) 4817 | | mstore(0x80, p3) 4818 | | writeString(0xa0, p1) 4819 | | } 4820 | | _sendLogPayload(0x1c, 0xc4); 4821 | | /// @solidity memory-safe-assembly 4822 | | assembly { 4823 | | mstore(0x00, m0) 4824 | | mstore(0x20, m1) 4825 | | mstore(0x40, m2) 4826 | | mstore(0x60, m3) 4827 | | mstore(0x80, m4) 4828 | | mstore(0xa0, m5) 4829 | | mstore(0xc0, m6) 4830 | | } 4831 | | } 4832 | | 4833 | | function log(address p0, bytes32 p1, address p2, bool p3) internal pure { 4834 | | bytes32 m0; 4835 | | bytes32 m1; 4836 | | bytes32 m2; 4837 | | bytes32 m3; 4838 | | bytes32 m4; 4839 | | bytes32 m5; 4840 | | bytes32 m6; 4841 | | /// @solidity memory-safe-assembly 4842 | | assembly { 4843 | | function writeString(pos, w) { 4844 | | let length := 0 4845 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4846 | | mstore(pos, length) 4847 | | let shift := sub(256, shl(3, length)) 4848 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4849 | | } 4850 | | m0 := mload(0x00) 4851 | | m1 := mload(0x20) 4852 | | m2 := mload(0x40) 4853 | | m3 := mload(0x60) 4854 | | m4 := mload(0x80) 4855 | | m5 := mload(0xa0) 4856 | | m6 := mload(0xc0) 4857 | | // Selector of `log(address,string,address,bool)`. 4858 | | mstore(0x00, 0x0df12b76) 4859 | | mstore(0x20, p0) 4860 | | mstore(0x40, 0x80) 4861 | | mstore(0x60, p2) 4862 | | mstore(0x80, p3) 4863 | | writeString(0xa0, p1) 4864 | | } 4865 | | _sendLogPayload(0x1c, 0xc4); 4866 | | /// @solidity memory-safe-assembly 4867 | | assembly { 4868 | | mstore(0x00, m0) 4869 | | mstore(0x20, m1) 4870 | | mstore(0x40, m2) 4871 | | mstore(0x60, m3) 4872 | | mstore(0x80, m4) 4873 | | mstore(0xa0, m5) 4874 | | mstore(0xc0, m6) 4875 | | } 4876 | | } 4877 | | 4878 | | function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure { 4879 | | bytes32 m0; 4880 | | bytes32 m1; 4881 | | bytes32 m2; 4882 | | bytes32 m3; 4883 | | bytes32 m4; 4884 | | bytes32 m5; 4885 | | bytes32 m6; 4886 | | /// @solidity memory-safe-assembly 4887 | | assembly { 4888 | | function writeString(pos, w) { 4889 | | let length := 0 4890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4891 | | mstore(pos, length) 4892 | | let shift := sub(256, shl(3, length)) 4893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4894 | | } 4895 | | m0 := mload(0x00) 4896 | | m1 := mload(0x20) 4897 | | m2 := mload(0x40) 4898 | | m3 := mload(0x60) 4899 | | m4 := mload(0x80) 4900 | | m5 := mload(0xa0) 4901 | | m6 := mload(0xc0) 4902 | | // Selector of `log(address,string,address,uint256)`. 4903 | | mstore(0x00, 0x457fe3cf) 4904 | | mstore(0x20, p0) 4905 | | mstore(0x40, 0x80) 4906 | | mstore(0x60, p2) 4907 | | mstore(0x80, p3) 4908 | | writeString(0xa0, p1) 4909 | | } 4910 | | _sendLogPayload(0x1c, 0xc4); 4911 | | /// @solidity memory-safe-assembly 4912 | | assembly { 4913 | | mstore(0x00, m0) 4914 | | mstore(0x20, m1) 4915 | | mstore(0x40, m2) 4916 | | mstore(0x60, m3) 4917 | | mstore(0x80, m4) 4918 | | mstore(0xa0, m5) 4919 | | mstore(0xc0, m6) 4920 | | } 4921 | | } 4922 | | 4923 | | function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure { 4924 | | bytes32 m0; 4925 | | bytes32 m1; 4926 | | bytes32 m2; 4927 | | bytes32 m3; 4928 | | bytes32 m4; 4929 | | bytes32 m5; 4930 | | bytes32 m6; 4931 | | bytes32 m7; 4932 | | bytes32 m8; 4933 | | /// @solidity memory-safe-assembly 4934 | | assembly { 4935 | | function writeString(pos, w) { 4936 | | let length := 0 4937 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4938 | | mstore(pos, length) 4939 | | let shift := sub(256, shl(3, length)) 4940 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4941 | | } 4942 | | m0 := mload(0x00) 4943 | | m1 := mload(0x20) 4944 | | m2 := mload(0x40) 4945 | | m3 := mload(0x60) 4946 | | m4 := mload(0x80) 4947 | | m5 := mload(0xa0) 4948 | | m6 := mload(0xc0) 4949 | | m7 := mload(0xe0) 4950 | | m8 := mload(0x100) 4951 | | // Selector of `log(address,string,address,string)`. 4952 | | mstore(0x00, 0xf7e36245) 4953 | | mstore(0x20, p0) 4954 | | mstore(0x40, 0x80) 4955 | | mstore(0x60, p2) 4956 | | mstore(0x80, 0xc0) 4957 | | writeString(0xa0, p1) 4958 | | writeString(0xe0, p3) 4959 | | } 4960 | | _sendLogPayload(0x1c, 0x104); 4961 | | /// @solidity memory-safe-assembly 4962 | | assembly { 4963 | | mstore(0x00, m0) 4964 | | mstore(0x20, m1) 4965 | | mstore(0x40, m2) 4966 | | mstore(0x60, m3) 4967 | | mstore(0x80, m4) 4968 | | mstore(0xa0, m5) 4969 | | mstore(0xc0, m6) 4970 | | mstore(0xe0, m7) 4971 | | mstore(0x100, m8) 4972 | | } 4973 | | } 4974 | | 4975 | | function log(address p0, bytes32 p1, bool p2, address p3) internal pure { 4976 | | bytes32 m0; 4977 | | bytes32 m1; 4978 | | bytes32 m2; 4979 | | bytes32 m3; 4980 | | bytes32 m4; 4981 | | bytes32 m5; 4982 | | bytes32 m6; 4983 | | /// @solidity memory-safe-assembly 4984 | | assembly { 4985 | | function writeString(pos, w) { 4986 | | let length := 0 4987 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 4988 | | mstore(pos, length) 4989 | | let shift := sub(256, shl(3, length)) 4990 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 4991 | | } 4992 | | m0 := mload(0x00) 4993 | | m1 := mload(0x20) 4994 | | m2 := mload(0x40) 4995 | | m3 := mload(0x60) 4996 | | m4 := mload(0x80) 4997 | | m5 := mload(0xa0) 4998 | | m6 := mload(0xc0) 4999 | | // Selector of `log(address,string,bool,address)`. 5000 | | mstore(0x00, 0x205871c2) 5001 | | mstore(0x20, p0) 5002 | | mstore(0x40, 0x80) 5003 | | mstore(0x60, p2) 5004 | | mstore(0x80, p3) 5005 | | writeString(0xa0, p1) 5006 | | } 5007 | | _sendLogPayload(0x1c, 0xc4); 5008 | | /// @solidity memory-safe-assembly 5009 | | assembly { 5010 | | mstore(0x00, m0) 5011 | | mstore(0x20, m1) 5012 | | mstore(0x40, m2) 5013 | | mstore(0x60, m3) 5014 | | mstore(0x80, m4) 5015 | | mstore(0xa0, m5) 5016 | | mstore(0xc0, m6) 5017 | | } 5018 | | } 5019 | | 5020 | | function log(address p0, bytes32 p1, bool p2, bool p3) internal pure { 5021 | | bytes32 m0; 5022 | | bytes32 m1; 5023 | | bytes32 m2; 5024 | | bytes32 m3; 5025 | | bytes32 m4; 5026 | | bytes32 m5; 5027 | | bytes32 m6; 5028 | | /// @solidity memory-safe-assembly 5029 | | assembly { 5030 | | function writeString(pos, w) { 5031 | | let length := 0 5032 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5033 | | mstore(pos, length) 5034 | | let shift := sub(256, shl(3, length)) 5035 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5036 | | } 5037 | | m0 := mload(0x00) 5038 | | m1 := mload(0x20) 5039 | | m2 := mload(0x40) 5040 | | m3 := mload(0x60) 5041 | | m4 := mload(0x80) 5042 | | m5 := mload(0xa0) 5043 | | m6 := mload(0xc0) 5044 | | // Selector of `log(address,string,bool,bool)`. 5045 | | mstore(0x00, 0x5f1d5c9f) 5046 | | mstore(0x20, p0) 5047 | | mstore(0x40, 0x80) 5048 | | mstore(0x60, p2) 5049 | | mstore(0x80, p3) 5050 | | writeString(0xa0, p1) 5051 | | } 5052 | | _sendLogPayload(0x1c, 0xc4); 5053 | | /// @solidity memory-safe-assembly 5054 | | assembly { 5055 | | mstore(0x00, m0) 5056 | | mstore(0x20, m1) 5057 | | mstore(0x40, m2) 5058 | | mstore(0x60, m3) 5059 | | mstore(0x80, m4) 5060 | | mstore(0xa0, m5) 5061 | | mstore(0xc0, m6) 5062 | | } 5063 | | } 5064 | | 5065 | | function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure { 5066 | | bytes32 m0; 5067 | | bytes32 m1; 5068 | | bytes32 m2; 5069 | | bytes32 m3; 5070 | | bytes32 m4; 5071 | | bytes32 m5; 5072 | | bytes32 m6; 5073 | | /// @solidity memory-safe-assembly 5074 | | assembly { 5075 | | function writeString(pos, w) { 5076 | | let length := 0 5077 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5078 | | mstore(pos, length) 5079 | | let shift := sub(256, shl(3, length)) 5080 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5081 | | } 5082 | | m0 := mload(0x00) 5083 | | m1 := mload(0x20) 5084 | | m2 := mload(0x40) 5085 | | m3 := mload(0x60) 5086 | | m4 := mload(0x80) 5087 | | m5 := mload(0xa0) 5088 | | m6 := mload(0xc0) 5089 | | // Selector of `log(address,string,bool,uint256)`. 5090 | | mstore(0x00, 0x515e38b6) 5091 | | mstore(0x20, p0) 5092 | | mstore(0x40, 0x80) 5093 | | mstore(0x60, p2) 5094 | | mstore(0x80, p3) 5095 | | writeString(0xa0, p1) 5096 | | } 5097 | | _sendLogPayload(0x1c, 0xc4); 5098 | | /// @solidity memory-safe-assembly 5099 | | assembly { 5100 | | mstore(0x00, m0) 5101 | | mstore(0x20, m1) 5102 | | mstore(0x40, m2) 5103 | | mstore(0x60, m3) 5104 | | mstore(0x80, m4) 5105 | | mstore(0xa0, m5) 5106 | | mstore(0xc0, m6) 5107 | | } 5108 | | } 5109 | | 5110 | | function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure { 5111 | | bytes32 m0; 5112 | | bytes32 m1; 5113 | | bytes32 m2; 5114 | | bytes32 m3; 5115 | | bytes32 m4; 5116 | | bytes32 m5; 5117 | | bytes32 m6; 5118 | | bytes32 m7; 5119 | | bytes32 m8; 5120 | | /// @solidity memory-safe-assembly 5121 | | assembly { 5122 | | function writeString(pos, w) { 5123 | | let length := 0 5124 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5125 | | mstore(pos, length) 5126 | | let shift := sub(256, shl(3, length)) 5127 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5128 | | } 5129 | | m0 := mload(0x00) 5130 | | m1 := mload(0x20) 5131 | | m2 := mload(0x40) 5132 | | m3 := mload(0x60) 5133 | | m4 := mload(0x80) 5134 | | m5 := mload(0xa0) 5135 | | m6 := mload(0xc0) 5136 | | m7 := mload(0xe0) 5137 | | m8 := mload(0x100) 5138 | | // Selector of `log(address,string,bool,string)`. 5139 | | mstore(0x00, 0xbc0b61fe) 5140 | | mstore(0x20, p0) 5141 | | mstore(0x40, 0x80) 5142 | | mstore(0x60, p2) 5143 | | mstore(0x80, 0xc0) 5144 | | writeString(0xa0, p1) 5145 | | writeString(0xe0, p3) 5146 | | } 5147 | | _sendLogPayload(0x1c, 0x104); 5148 | | /// @solidity memory-safe-assembly 5149 | | assembly { 5150 | | mstore(0x00, m0) 5151 | | mstore(0x20, m1) 5152 | | mstore(0x40, m2) 5153 | | mstore(0x60, m3) 5154 | | mstore(0x80, m4) 5155 | | mstore(0xa0, m5) 5156 | | mstore(0xc0, m6) 5157 | | mstore(0xe0, m7) 5158 | | mstore(0x100, m8) 5159 | | } 5160 | | } 5161 | | 5162 | | function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure { 5163 | | bytes32 m0; 5164 | | bytes32 m1; 5165 | | bytes32 m2; 5166 | | bytes32 m3; 5167 | | bytes32 m4; 5168 | | bytes32 m5; 5169 | | bytes32 m6; 5170 | | /// @solidity memory-safe-assembly 5171 | | assembly { 5172 | | function writeString(pos, w) { 5173 | | let length := 0 5174 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5175 | | mstore(pos, length) 5176 | | let shift := sub(256, shl(3, length)) 5177 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5178 | | } 5179 | | m0 := mload(0x00) 5180 | | m1 := mload(0x20) 5181 | | m2 := mload(0x40) 5182 | | m3 := mload(0x60) 5183 | | m4 := mload(0x80) 5184 | | m5 := mload(0xa0) 5185 | | m6 := mload(0xc0) 5186 | | // Selector of `log(address,string,uint256,address)`. 5187 | | mstore(0x00, 0x63183678) 5188 | | mstore(0x20, p0) 5189 | | mstore(0x40, 0x80) 5190 | | mstore(0x60, p2) 5191 | | mstore(0x80, p3) 5192 | | writeString(0xa0, p1) 5193 | | } 5194 | | _sendLogPayload(0x1c, 0xc4); 5195 | | /// @solidity memory-safe-assembly 5196 | | assembly { 5197 | | mstore(0x00, m0) 5198 | | mstore(0x20, m1) 5199 | | mstore(0x40, m2) 5200 | | mstore(0x60, m3) 5201 | | mstore(0x80, m4) 5202 | | mstore(0xa0, m5) 5203 | | mstore(0xc0, m6) 5204 | | } 5205 | | } 5206 | | 5207 | | function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure { 5208 | | bytes32 m0; 5209 | | bytes32 m1; 5210 | | bytes32 m2; 5211 | | bytes32 m3; 5212 | | bytes32 m4; 5213 | | bytes32 m5; 5214 | | bytes32 m6; 5215 | | /// @solidity memory-safe-assembly 5216 | | assembly { 5217 | | function writeString(pos, w) { 5218 | | let length := 0 5219 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5220 | | mstore(pos, length) 5221 | | let shift := sub(256, shl(3, length)) 5222 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5223 | | } 5224 | | m0 := mload(0x00) 5225 | | m1 := mload(0x20) 5226 | | m2 := mload(0x40) 5227 | | m3 := mload(0x60) 5228 | | m4 := mload(0x80) 5229 | | m5 := mload(0xa0) 5230 | | m6 := mload(0xc0) 5231 | | // Selector of `log(address,string,uint256,bool)`. 5232 | | mstore(0x00, 0x0ef7e050) 5233 | | mstore(0x20, p0) 5234 | | mstore(0x40, 0x80) 5235 | | mstore(0x60, p2) 5236 | | mstore(0x80, p3) 5237 | | writeString(0xa0, p1) 5238 | | } 5239 | | _sendLogPayload(0x1c, 0xc4); 5240 | | /// @solidity memory-safe-assembly 5241 | | assembly { 5242 | | mstore(0x00, m0) 5243 | | mstore(0x20, m1) 5244 | | mstore(0x40, m2) 5245 | | mstore(0x60, m3) 5246 | | mstore(0x80, m4) 5247 | | mstore(0xa0, m5) 5248 | | mstore(0xc0, m6) 5249 | | } 5250 | | } 5251 | | 5252 | | function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { 5253 | | bytes32 m0; 5254 | | bytes32 m1; 5255 | | bytes32 m2; 5256 | | bytes32 m3; 5257 | | bytes32 m4; 5258 | | bytes32 m5; 5259 | | bytes32 m6; 5260 | | /// @solidity memory-safe-assembly 5261 | | assembly { 5262 | | function writeString(pos, w) { 5263 | | let length := 0 5264 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5265 | | mstore(pos, length) 5266 | | let shift := sub(256, shl(3, length)) 5267 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5268 | | } 5269 | | m0 := mload(0x00) 5270 | | m1 := mload(0x20) 5271 | | m2 := mload(0x40) 5272 | | m3 := mload(0x60) 5273 | | m4 := mload(0x80) 5274 | | m5 := mload(0xa0) 5275 | | m6 := mload(0xc0) 5276 | | // Selector of `log(address,string,uint256,uint256)`. 5277 | | mstore(0x00, 0x1dc8e1b8) 5278 | | mstore(0x20, p0) 5279 | | mstore(0x40, 0x80) 5280 | | mstore(0x60, p2) 5281 | | mstore(0x80, p3) 5282 | | writeString(0xa0, p1) 5283 | | } 5284 | | _sendLogPayload(0x1c, 0xc4); 5285 | | /// @solidity memory-safe-assembly 5286 | | assembly { 5287 | | mstore(0x00, m0) 5288 | | mstore(0x20, m1) 5289 | | mstore(0x40, m2) 5290 | | mstore(0x60, m3) 5291 | | mstore(0x80, m4) 5292 | | mstore(0xa0, m5) 5293 | | mstore(0xc0, m6) 5294 | | } 5295 | | } 5296 | | 5297 | | function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { 5298 | | bytes32 m0; 5299 | | bytes32 m1; 5300 | | bytes32 m2; 5301 | | bytes32 m3; 5302 | | bytes32 m4; 5303 | | bytes32 m5; 5304 | | bytes32 m6; 5305 | | bytes32 m7; 5306 | | bytes32 m8; 5307 | | /// @solidity memory-safe-assembly 5308 | | assembly { 5309 | | function writeString(pos, w) { 5310 | | let length := 0 5311 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5312 | | mstore(pos, length) 5313 | | let shift := sub(256, shl(3, length)) 5314 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5315 | | } 5316 | | m0 := mload(0x00) 5317 | | m1 := mload(0x20) 5318 | | m2 := mload(0x40) 5319 | | m3 := mload(0x60) 5320 | | m4 := mload(0x80) 5321 | | m5 := mload(0xa0) 5322 | | m6 := mload(0xc0) 5323 | | m7 := mload(0xe0) 5324 | | m8 := mload(0x100) 5325 | | // Selector of `log(address,string,uint256,string)`. 5326 | | mstore(0x00, 0x448830a8) 5327 | | mstore(0x20, p0) 5328 | | mstore(0x40, 0x80) 5329 | | mstore(0x60, p2) 5330 | | mstore(0x80, 0xc0) 5331 | | writeString(0xa0, p1) 5332 | | writeString(0xe0, p3) 5333 | | } 5334 | | _sendLogPayload(0x1c, 0x104); 5335 | | /// @solidity memory-safe-assembly 5336 | | assembly { 5337 | | mstore(0x00, m0) 5338 | | mstore(0x20, m1) 5339 | | mstore(0x40, m2) 5340 | | mstore(0x60, m3) 5341 | | mstore(0x80, m4) 5342 | | mstore(0xa0, m5) 5343 | | mstore(0xc0, m6) 5344 | | mstore(0xe0, m7) 5345 | | mstore(0x100, m8) 5346 | | } 5347 | | } 5348 | | 5349 | | function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure { 5350 | | bytes32 m0; 5351 | | bytes32 m1; 5352 | | bytes32 m2; 5353 | | bytes32 m3; 5354 | | bytes32 m4; 5355 | | bytes32 m5; 5356 | | bytes32 m6; 5357 | | bytes32 m7; 5358 | | bytes32 m8; 5359 | | /// @solidity memory-safe-assembly 5360 | | assembly { 5361 | | function writeString(pos, w) { 5362 | | let length := 0 5363 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5364 | | mstore(pos, length) 5365 | | let shift := sub(256, shl(3, length)) 5366 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5367 | | } 5368 | | m0 := mload(0x00) 5369 | | m1 := mload(0x20) 5370 | | m2 := mload(0x40) 5371 | | m3 := mload(0x60) 5372 | | m4 := mload(0x80) 5373 | | m5 := mload(0xa0) 5374 | | m6 := mload(0xc0) 5375 | | m7 := mload(0xe0) 5376 | | m8 := mload(0x100) 5377 | | // Selector of `log(address,string,string,address)`. 5378 | | mstore(0x00, 0xa04e2f87) 5379 | | mstore(0x20, p0) 5380 | | mstore(0x40, 0x80) 5381 | | mstore(0x60, 0xc0) 5382 | | mstore(0x80, p3) 5383 | | writeString(0xa0, p1) 5384 | | writeString(0xe0, p2) 5385 | | } 5386 | | _sendLogPayload(0x1c, 0x104); 5387 | | /// @solidity memory-safe-assembly 5388 | | assembly { 5389 | | mstore(0x00, m0) 5390 | | mstore(0x20, m1) 5391 | | mstore(0x40, m2) 5392 | | mstore(0x60, m3) 5393 | | mstore(0x80, m4) 5394 | | mstore(0xa0, m5) 5395 | | mstore(0xc0, m6) 5396 | | mstore(0xe0, m7) 5397 | | mstore(0x100, m8) 5398 | | } 5399 | | } 5400 | | 5401 | | function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure { 5402 | | bytes32 m0; 5403 | | bytes32 m1; 5404 | | bytes32 m2; 5405 | | bytes32 m3; 5406 | | bytes32 m4; 5407 | | bytes32 m5; 5408 | | bytes32 m6; 5409 | | bytes32 m7; 5410 | | bytes32 m8; 5411 | | /// @solidity memory-safe-assembly 5412 | | assembly { 5413 | | function writeString(pos, w) { 5414 | | let length := 0 5415 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5416 | | mstore(pos, length) 5417 | | let shift := sub(256, shl(3, length)) 5418 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5419 | | } 5420 | | m0 := mload(0x00) 5421 | | m1 := mload(0x20) 5422 | | m2 := mload(0x40) 5423 | | m3 := mload(0x60) 5424 | | m4 := mload(0x80) 5425 | | m5 := mload(0xa0) 5426 | | m6 := mload(0xc0) 5427 | | m7 := mload(0xe0) 5428 | | m8 := mload(0x100) 5429 | | // Selector of `log(address,string,string,bool)`. 5430 | | mstore(0x00, 0x35a5071f) 5431 | | mstore(0x20, p0) 5432 | | mstore(0x40, 0x80) 5433 | | mstore(0x60, 0xc0) 5434 | | mstore(0x80, p3) 5435 | | writeString(0xa0, p1) 5436 | | writeString(0xe0, p2) 5437 | | } 5438 | | _sendLogPayload(0x1c, 0x104); 5439 | | /// @solidity memory-safe-assembly 5440 | | assembly { 5441 | | mstore(0x00, m0) 5442 | | mstore(0x20, m1) 5443 | | mstore(0x40, m2) 5444 | | mstore(0x60, m3) 5445 | | mstore(0x80, m4) 5446 | | mstore(0xa0, m5) 5447 | | mstore(0xc0, m6) 5448 | | mstore(0xe0, m7) 5449 | | mstore(0x100, m8) 5450 | | } 5451 | | } 5452 | | 5453 | | function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { 5454 | | bytes32 m0; 5455 | | bytes32 m1; 5456 | | bytes32 m2; 5457 | | bytes32 m3; 5458 | | bytes32 m4; 5459 | | bytes32 m5; 5460 | | bytes32 m6; 5461 | | bytes32 m7; 5462 | | bytes32 m8; 5463 | | /// @solidity memory-safe-assembly 5464 | | assembly { 5465 | | function writeString(pos, w) { 5466 | | let length := 0 5467 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5468 | | mstore(pos, length) 5469 | | let shift := sub(256, shl(3, length)) 5470 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5471 | | } 5472 | | m0 := mload(0x00) 5473 | | m1 := mload(0x20) 5474 | | m2 := mload(0x40) 5475 | | m3 := mload(0x60) 5476 | | m4 := mload(0x80) 5477 | | m5 := mload(0xa0) 5478 | | m6 := mload(0xc0) 5479 | | m7 := mload(0xe0) 5480 | | m8 := mload(0x100) 5481 | | // Selector of `log(address,string,string,uint256)`. 5482 | | mstore(0x00, 0x159f8927) 5483 | | mstore(0x20, p0) 5484 | | mstore(0x40, 0x80) 5485 | | mstore(0x60, 0xc0) 5486 | | mstore(0x80, p3) 5487 | | writeString(0xa0, p1) 5488 | | writeString(0xe0, p2) 5489 | | } 5490 | | _sendLogPayload(0x1c, 0x104); 5491 | | /// @solidity memory-safe-assembly 5492 | | assembly { 5493 | | mstore(0x00, m0) 5494 | | mstore(0x20, m1) 5495 | | mstore(0x40, m2) 5496 | | mstore(0x60, m3) 5497 | | mstore(0x80, m4) 5498 | | mstore(0xa0, m5) 5499 | | mstore(0xc0, m6) 5500 | | mstore(0xe0, m7) 5501 | | mstore(0x100, m8) 5502 | | } 5503 | | } 5504 | | 5505 | | function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { 5506 | | bytes32 m0; 5507 | | bytes32 m1; 5508 | | bytes32 m2; 5509 | | bytes32 m3; 5510 | | bytes32 m4; 5511 | | bytes32 m5; 5512 | | bytes32 m6; 5513 | | bytes32 m7; 5514 | | bytes32 m8; 5515 | | bytes32 m9; 5516 | | bytes32 m10; 5517 | | /// @solidity memory-safe-assembly 5518 | | assembly { 5519 | | function writeString(pos, w) { 5520 | | let length := 0 5521 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5522 | | mstore(pos, length) 5523 | | let shift := sub(256, shl(3, length)) 5524 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5525 | | } 5526 | | m0 := mload(0x00) 5527 | | m1 := mload(0x20) 5528 | | m2 := mload(0x40) 5529 | | m3 := mload(0x60) 5530 | | m4 := mload(0x80) 5531 | | m5 := mload(0xa0) 5532 | | m6 := mload(0xc0) 5533 | | m7 := mload(0xe0) 5534 | | m8 := mload(0x100) 5535 | | m9 := mload(0x120) 5536 | | m10 := mload(0x140) 5537 | | // Selector of `log(address,string,string,string)`. 5538 | | mstore(0x00, 0x5d02c50b) 5539 | | mstore(0x20, p0) 5540 | | mstore(0x40, 0x80) 5541 | | mstore(0x60, 0xc0) 5542 | | mstore(0x80, 0x100) 5543 | | writeString(0xa0, p1) 5544 | | writeString(0xe0, p2) 5545 | | writeString(0x120, p3) 5546 | | } 5547 | | _sendLogPayload(0x1c, 0x144); 5548 | | /// @solidity memory-safe-assembly 5549 | | assembly { 5550 | | mstore(0x00, m0) 5551 | | mstore(0x20, m1) 5552 | | mstore(0x40, m2) 5553 | | mstore(0x60, m3) 5554 | | mstore(0x80, m4) 5555 | | mstore(0xa0, m5) 5556 | | mstore(0xc0, m6) 5557 | | mstore(0xe0, m7) 5558 | | mstore(0x100, m8) 5559 | | mstore(0x120, m9) 5560 | | mstore(0x140, m10) 5561 | | } 5562 | | } 5563 | | 5564 | | function log(bool p0, address p1, address p2, address p3) internal pure { 5565 | | bytes32 m0; 5566 | | bytes32 m1; 5567 | | bytes32 m2; 5568 | | bytes32 m3; 5569 | | bytes32 m4; 5570 | | /// @solidity memory-safe-assembly 5571 | | assembly { 5572 | | m0 := mload(0x00) 5573 | | m1 := mload(0x20) 5574 | | m2 := mload(0x40) 5575 | | m3 := mload(0x60) 5576 | | m4 := mload(0x80) 5577 | | // Selector of `log(bool,address,address,address)`. 5578 | | mstore(0x00, 0x1d14d001) 5579 | | mstore(0x20, p0) 5580 | | mstore(0x40, p1) 5581 | | mstore(0x60, p2) 5582 | | mstore(0x80, p3) 5583 | | } 5584 | | _sendLogPayload(0x1c, 0x84); 5585 | | /// @solidity memory-safe-assembly 5586 | | assembly { 5587 | | mstore(0x00, m0) 5588 | | mstore(0x20, m1) 5589 | | mstore(0x40, m2) 5590 | | mstore(0x60, m3) 5591 | | mstore(0x80, m4) 5592 | | } 5593 | | } 5594 | | 5595 | | function log(bool p0, address p1, address p2, bool p3) internal pure { 5596 | | bytes32 m0; 5597 | | bytes32 m1; 5598 | | bytes32 m2; 5599 | | bytes32 m3; 5600 | | bytes32 m4; 5601 | | /// @solidity memory-safe-assembly 5602 | | assembly { 5603 | | m0 := mload(0x00) 5604 | | m1 := mload(0x20) 5605 | | m2 := mload(0x40) 5606 | | m3 := mload(0x60) 5607 | | m4 := mload(0x80) 5608 | | // Selector of `log(bool,address,address,bool)`. 5609 | | mstore(0x00, 0x46600be0) 5610 | | mstore(0x20, p0) 5611 | | mstore(0x40, p1) 5612 | | mstore(0x60, p2) 5613 | | mstore(0x80, p3) 5614 | | } 5615 | | _sendLogPayload(0x1c, 0x84); 5616 | | /// @solidity memory-safe-assembly 5617 | | assembly { 5618 | | mstore(0x00, m0) 5619 | | mstore(0x20, m1) 5620 | | mstore(0x40, m2) 5621 | | mstore(0x60, m3) 5622 | | mstore(0x80, m4) 5623 | | } 5624 | | } 5625 | | 5626 | | function log(bool p0, address p1, address p2, uint256 p3) internal pure { 5627 | | bytes32 m0; 5628 | | bytes32 m1; 5629 | | bytes32 m2; 5630 | | bytes32 m3; 5631 | | bytes32 m4; 5632 | | /// @solidity memory-safe-assembly 5633 | | assembly { 5634 | | m0 := mload(0x00) 5635 | | m1 := mload(0x20) 5636 | | m2 := mload(0x40) 5637 | | m3 := mload(0x60) 5638 | | m4 := mload(0x80) 5639 | | // Selector of `log(bool,address,address,uint256)`. 5640 | | mstore(0x00, 0x0c66d1be) 5641 | | mstore(0x20, p0) 5642 | | mstore(0x40, p1) 5643 | | mstore(0x60, p2) 5644 | | mstore(0x80, p3) 5645 | | } 5646 | | _sendLogPayload(0x1c, 0x84); 5647 | | /// @solidity memory-safe-assembly 5648 | | assembly { 5649 | | mstore(0x00, m0) 5650 | | mstore(0x20, m1) 5651 | | mstore(0x40, m2) 5652 | | mstore(0x60, m3) 5653 | | mstore(0x80, m4) 5654 | | } 5655 | | } 5656 | | 5657 | | function log(bool p0, address p1, address p2, bytes32 p3) internal pure { 5658 | | bytes32 m0; 5659 | | bytes32 m1; 5660 | | bytes32 m2; 5661 | | bytes32 m3; 5662 | | bytes32 m4; 5663 | | bytes32 m5; 5664 | | bytes32 m6; 5665 | | /// @solidity memory-safe-assembly 5666 | | assembly { 5667 | | function writeString(pos, w) { 5668 | | let length := 0 5669 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5670 | | mstore(pos, length) 5671 | | let shift := sub(256, shl(3, length)) 5672 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5673 | | } 5674 | | m0 := mload(0x00) 5675 | | m1 := mload(0x20) 5676 | | m2 := mload(0x40) 5677 | | m3 := mload(0x60) 5678 | | m4 := mload(0x80) 5679 | | m5 := mload(0xa0) 5680 | | m6 := mload(0xc0) 5681 | | // Selector of `log(bool,address,address,string)`. 5682 | | mstore(0x00, 0xd812a167) 5683 | | mstore(0x20, p0) 5684 | | mstore(0x40, p1) 5685 | | mstore(0x60, p2) 5686 | | mstore(0x80, 0x80) 5687 | | writeString(0xa0, p3) 5688 | | } 5689 | | _sendLogPayload(0x1c, 0xc4); 5690 | | /// @solidity memory-safe-assembly 5691 | | assembly { 5692 | | mstore(0x00, m0) 5693 | | mstore(0x20, m1) 5694 | | mstore(0x40, m2) 5695 | | mstore(0x60, m3) 5696 | | mstore(0x80, m4) 5697 | | mstore(0xa0, m5) 5698 | | mstore(0xc0, m6) 5699 | | } 5700 | | } 5701 | | 5702 | | function log(bool p0, address p1, bool p2, address p3) internal pure { 5703 | | bytes32 m0; 5704 | | bytes32 m1; 5705 | | bytes32 m2; 5706 | | bytes32 m3; 5707 | | bytes32 m4; 5708 | | /// @solidity memory-safe-assembly 5709 | | assembly { 5710 | | m0 := mload(0x00) 5711 | | m1 := mload(0x20) 5712 | | m2 := mload(0x40) 5713 | | m3 := mload(0x60) 5714 | | m4 := mload(0x80) 5715 | | // Selector of `log(bool,address,bool,address)`. 5716 | | mstore(0x00, 0x1c41a336) 5717 | | mstore(0x20, p0) 5718 | | mstore(0x40, p1) 5719 | | mstore(0x60, p2) 5720 | | mstore(0x80, p3) 5721 | | } 5722 | | _sendLogPayload(0x1c, 0x84); 5723 | | /// @solidity memory-safe-assembly 5724 | | assembly { 5725 | | mstore(0x00, m0) 5726 | | mstore(0x20, m1) 5727 | | mstore(0x40, m2) 5728 | | mstore(0x60, m3) 5729 | | mstore(0x80, m4) 5730 | | } 5731 | | } 5732 | | 5733 | | function log(bool p0, address p1, bool p2, bool p3) internal pure { 5734 | | bytes32 m0; 5735 | | bytes32 m1; 5736 | | bytes32 m2; 5737 | | bytes32 m3; 5738 | | bytes32 m4; 5739 | | /// @solidity memory-safe-assembly 5740 | | assembly { 5741 | | m0 := mload(0x00) 5742 | | m1 := mload(0x20) 5743 | | m2 := mload(0x40) 5744 | | m3 := mload(0x60) 5745 | | m4 := mload(0x80) 5746 | | // Selector of `log(bool,address,bool,bool)`. 5747 | | mstore(0x00, 0x6a9c478b) 5748 | | mstore(0x20, p0) 5749 | | mstore(0x40, p1) 5750 | | mstore(0x60, p2) 5751 | | mstore(0x80, p3) 5752 | | } 5753 | | _sendLogPayload(0x1c, 0x84); 5754 | | /// @solidity memory-safe-assembly 5755 | | assembly { 5756 | | mstore(0x00, m0) 5757 | | mstore(0x20, m1) 5758 | | mstore(0x40, m2) 5759 | | mstore(0x60, m3) 5760 | | mstore(0x80, m4) 5761 | | } 5762 | | } 5763 | | 5764 | | function log(bool p0, address p1, bool p2, uint256 p3) internal pure { 5765 | | bytes32 m0; 5766 | | bytes32 m1; 5767 | | bytes32 m2; 5768 | | bytes32 m3; 5769 | | bytes32 m4; 5770 | | /// @solidity memory-safe-assembly 5771 | | assembly { 5772 | | m0 := mload(0x00) 5773 | | m1 := mload(0x20) 5774 | | m2 := mload(0x40) 5775 | | m3 := mload(0x60) 5776 | | m4 := mload(0x80) 5777 | | // Selector of `log(bool,address,bool,uint256)`. 5778 | | mstore(0x00, 0x07831502) 5779 | | mstore(0x20, p0) 5780 | | mstore(0x40, p1) 5781 | | mstore(0x60, p2) 5782 | | mstore(0x80, p3) 5783 | | } 5784 | | _sendLogPayload(0x1c, 0x84); 5785 | | /// @solidity memory-safe-assembly 5786 | | assembly { 5787 | | mstore(0x00, m0) 5788 | | mstore(0x20, m1) 5789 | | mstore(0x40, m2) 5790 | | mstore(0x60, m3) 5791 | | mstore(0x80, m4) 5792 | | } 5793 | | } 5794 | | 5795 | | function log(bool p0, address p1, bool p2, bytes32 p3) internal pure { 5796 | | bytes32 m0; 5797 | | bytes32 m1; 5798 | | bytes32 m2; 5799 | | bytes32 m3; 5800 | | bytes32 m4; 5801 | | bytes32 m5; 5802 | | bytes32 m6; 5803 | | /// @solidity memory-safe-assembly 5804 | | assembly { 5805 | | function writeString(pos, w) { 5806 | | let length := 0 5807 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5808 | | mstore(pos, length) 5809 | | let shift := sub(256, shl(3, length)) 5810 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5811 | | } 5812 | | m0 := mload(0x00) 5813 | | m1 := mload(0x20) 5814 | | m2 := mload(0x40) 5815 | | m3 := mload(0x60) 5816 | | m4 := mload(0x80) 5817 | | m5 := mload(0xa0) 5818 | | m6 := mload(0xc0) 5819 | | // Selector of `log(bool,address,bool,string)`. 5820 | | mstore(0x00, 0x4a66cb34) 5821 | | mstore(0x20, p0) 5822 | | mstore(0x40, p1) 5823 | | mstore(0x60, p2) 5824 | | mstore(0x80, 0x80) 5825 | | writeString(0xa0, p3) 5826 | | } 5827 | | _sendLogPayload(0x1c, 0xc4); 5828 | | /// @solidity memory-safe-assembly 5829 | | assembly { 5830 | | mstore(0x00, m0) 5831 | | mstore(0x20, m1) 5832 | | mstore(0x40, m2) 5833 | | mstore(0x60, m3) 5834 | | mstore(0x80, m4) 5835 | | mstore(0xa0, m5) 5836 | | mstore(0xc0, m6) 5837 | | } 5838 | | } 5839 | | 5840 | | function log(bool p0, address p1, uint256 p2, address p3) internal pure { 5841 | | bytes32 m0; 5842 | | bytes32 m1; 5843 | | bytes32 m2; 5844 | | bytes32 m3; 5845 | | bytes32 m4; 5846 | | /// @solidity memory-safe-assembly 5847 | | assembly { 5848 | | m0 := mload(0x00) 5849 | | m1 := mload(0x20) 5850 | | m2 := mload(0x40) 5851 | | m3 := mload(0x60) 5852 | | m4 := mload(0x80) 5853 | | // Selector of `log(bool,address,uint256,address)`. 5854 | | mstore(0x00, 0x136b05dd) 5855 | | mstore(0x20, p0) 5856 | | mstore(0x40, p1) 5857 | | mstore(0x60, p2) 5858 | | mstore(0x80, p3) 5859 | | } 5860 | | _sendLogPayload(0x1c, 0x84); 5861 | | /// @solidity memory-safe-assembly 5862 | | assembly { 5863 | | mstore(0x00, m0) 5864 | | mstore(0x20, m1) 5865 | | mstore(0x40, m2) 5866 | | mstore(0x60, m3) 5867 | | mstore(0x80, m4) 5868 | | } 5869 | | } 5870 | | 5871 | | function log(bool p0, address p1, uint256 p2, bool p3) internal pure { 5872 | | bytes32 m0; 5873 | | bytes32 m1; 5874 | | bytes32 m2; 5875 | | bytes32 m3; 5876 | | bytes32 m4; 5877 | | /// @solidity memory-safe-assembly 5878 | | assembly { 5879 | | m0 := mload(0x00) 5880 | | m1 := mload(0x20) 5881 | | m2 := mload(0x40) 5882 | | m3 := mload(0x60) 5883 | | m4 := mload(0x80) 5884 | | // Selector of `log(bool,address,uint256,bool)`. 5885 | | mstore(0x00, 0xd6019f1c) 5886 | | mstore(0x20, p0) 5887 | | mstore(0x40, p1) 5888 | | mstore(0x60, p2) 5889 | | mstore(0x80, p3) 5890 | | } 5891 | | _sendLogPayload(0x1c, 0x84); 5892 | | /// @solidity memory-safe-assembly 5893 | | assembly { 5894 | | mstore(0x00, m0) 5895 | | mstore(0x20, m1) 5896 | | mstore(0x40, m2) 5897 | | mstore(0x60, m3) 5898 | | mstore(0x80, m4) 5899 | | } 5900 | | } 5901 | | 5902 | | function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { 5903 | | bytes32 m0; 5904 | | bytes32 m1; 5905 | | bytes32 m2; 5906 | | bytes32 m3; 5907 | | bytes32 m4; 5908 | | /// @solidity memory-safe-assembly 5909 | | assembly { 5910 | | m0 := mload(0x00) 5911 | | m1 := mload(0x20) 5912 | | m2 := mload(0x40) 5913 | | m3 := mload(0x60) 5914 | | m4 := mload(0x80) 5915 | | // Selector of `log(bool,address,uint256,uint256)`. 5916 | | mstore(0x00, 0x7bf181a1) 5917 | | mstore(0x20, p0) 5918 | | mstore(0x40, p1) 5919 | | mstore(0x60, p2) 5920 | | mstore(0x80, p3) 5921 | | } 5922 | | _sendLogPayload(0x1c, 0x84); 5923 | | /// @solidity memory-safe-assembly 5924 | | assembly { 5925 | | mstore(0x00, m0) 5926 | | mstore(0x20, m1) 5927 | | mstore(0x40, m2) 5928 | | mstore(0x60, m3) 5929 | | mstore(0x80, m4) 5930 | | } 5931 | | } 5932 | | 5933 | | function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure { 5934 | | bytes32 m0; 5935 | | bytes32 m1; 5936 | | bytes32 m2; 5937 | | bytes32 m3; 5938 | | bytes32 m4; 5939 | | bytes32 m5; 5940 | | bytes32 m6; 5941 | | /// @solidity memory-safe-assembly 5942 | | assembly { 5943 | | function writeString(pos, w) { 5944 | | let length := 0 5945 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5946 | | mstore(pos, length) 5947 | | let shift := sub(256, shl(3, length)) 5948 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5949 | | } 5950 | | m0 := mload(0x00) 5951 | | m1 := mload(0x20) 5952 | | m2 := mload(0x40) 5953 | | m3 := mload(0x60) 5954 | | m4 := mload(0x80) 5955 | | m5 := mload(0xa0) 5956 | | m6 := mload(0xc0) 5957 | | // Selector of `log(bool,address,uint256,string)`. 5958 | | mstore(0x00, 0x51f09ff8) 5959 | | mstore(0x20, p0) 5960 | | mstore(0x40, p1) 5961 | | mstore(0x60, p2) 5962 | | mstore(0x80, 0x80) 5963 | | writeString(0xa0, p3) 5964 | | } 5965 | | _sendLogPayload(0x1c, 0xc4); 5966 | | /// @solidity memory-safe-assembly 5967 | | assembly { 5968 | | mstore(0x00, m0) 5969 | | mstore(0x20, m1) 5970 | | mstore(0x40, m2) 5971 | | mstore(0x60, m3) 5972 | | mstore(0x80, m4) 5973 | | mstore(0xa0, m5) 5974 | | mstore(0xc0, m6) 5975 | | } 5976 | | } 5977 | | 5978 | | function log(bool p0, address p1, bytes32 p2, address p3) internal pure { 5979 | | bytes32 m0; 5980 | | bytes32 m1; 5981 | | bytes32 m2; 5982 | | bytes32 m3; 5983 | | bytes32 m4; 5984 | | bytes32 m5; 5985 | | bytes32 m6; 5986 | | /// @solidity memory-safe-assembly 5987 | | assembly { 5988 | | function writeString(pos, w) { 5989 | | let length := 0 5990 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 5991 | | mstore(pos, length) 5992 | | let shift := sub(256, shl(3, length)) 5993 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 5994 | | } 5995 | | m0 := mload(0x00) 5996 | | m1 := mload(0x20) 5997 | | m2 := mload(0x40) 5998 | | m3 := mload(0x60) 5999 | | m4 := mload(0x80) 6000 | | m5 := mload(0xa0) 6001 | | m6 := mload(0xc0) 6002 | | // Selector of `log(bool,address,string,address)`. 6003 | | mstore(0x00, 0x6f7c603e) 6004 | | mstore(0x20, p0) 6005 | | mstore(0x40, p1) 6006 | | mstore(0x60, 0x80) 6007 | | mstore(0x80, p3) 6008 | | writeString(0xa0, p2) 6009 | | } 6010 | | _sendLogPayload(0x1c, 0xc4); 6011 | | /// @solidity memory-safe-assembly 6012 | | assembly { 6013 | | mstore(0x00, m0) 6014 | | mstore(0x20, m1) 6015 | | mstore(0x40, m2) 6016 | | mstore(0x60, m3) 6017 | | mstore(0x80, m4) 6018 | | mstore(0xa0, m5) 6019 | | mstore(0xc0, m6) 6020 | | } 6021 | | } 6022 | | 6023 | | function log(bool p0, address p1, bytes32 p2, bool p3) internal pure { 6024 | | bytes32 m0; 6025 | | bytes32 m1; 6026 | | bytes32 m2; 6027 | | bytes32 m3; 6028 | | bytes32 m4; 6029 | | bytes32 m5; 6030 | | bytes32 m6; 6031 | | /// @solidity memory-safe-assembly 6032 | | assembly { 6033 | | function writeString(pos, w) { 6034 | | let length := 0 6035 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6036 | | mstore(pos, length) 6037 | | let shift := sub(256, shl(3, length)) 6038 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6039 | | } 6040 | | m0 := mload(0x00) 6041 | | m1 := mload(0x20) 6042 | | m2 := mload(0x40) 6043 | | m3 := mload(0x60) 6044 | | m4 := mload(0x80) 6045 | | m5 := mload(0xa0) 6046 | | m6 := mload(0xc0) 6047 | | // Selector of `log(bool,address,string,bool)`. 6048 | | mstore(0x00, 0xe2bfd60b) 6049 | | mstore(0x20, p0) 6050 | | mstore(0x40, p1) 6051 | | mstore(0x60, 0x80) 6052 | | mstore(0x80, p3) 6053 | | writeString(0xa0, p2) 6054 | | } 6055 | | _sendLogPayload(0x1c, 0xc4); 6056 | | /// @solidity memory-safe-assembly 6057 | | assembly { 6058 | | mstore(0x00, m0) 6059 | | mstore(0x20, m1) 6060 | | mstore(0x40, m2) 6061 | | mstore(0x60, m3) 6062 | | mstore(0x80, m4) 6063 | | mstore(0xa0, m5) 6064 | | mstore(0xc0, m6) 6065 | | } 6066 | | } 6067 | | 6068 | | function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure { 6069 | | bytes32 m0; 6070 | | bytes32 m1; 6071 | | bytes32 m2; 6072 | | bytes32 m3; 6073 | | bytes32 m4; 6074 | | bytes32 m5; 6075 | | bytes32 m6; 6076 | | /// @solidity memory-safe-assembly 6077 | | assembly { 6078 | | function writeString(pos, w) { 6079 | | let length := 0 6080 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6081 | | mstore(pos, length) 6082 | | let shift := sub(256, shl(3, length)) 6083 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6084 | | } 6085 | | m0 := mload(0x00) 6086 | | m1 := mload(0x20) 6087 | | m2 := mload(0x40) 6088 | | m3 := mload(0x60) 6089 | | m4 := mload(0x80) 6090 | | m5 := mload(0xa0) 6091 | | m6 := mload(0xc0) 6092 | | // Selector of `log(bool,address,string,uint256)`. 6093 | | mstore(0x00, 0xc21f64c7) 6094 | | mstore(0x20, p0) 6095 | | mstore(0x40, p1) 6096 | | mstore(0x60, 0x80) 6097 | | mstore(0x80, p3) 6098 | | writeString(0xa0, p2) 6099 | | } 6100 | | _sendLogPayload(0x1c, 0xc4); 6101 | | /// @solidity memory-safe-assembly 6102 | | assembly { 6103 | | mstore(0x00, m0) 6104 | | mstore(0x20, m1) 6105 | | mstore(0x40, m2) 6106 | | mstore(0x60, m3) 6107 | | mstore(0x80, m4) 6108 | | mstore(0xa0, m5) 6109 | | mstore(0xc0, m6) 6110 | | } 6111 | | } 6112 | | 6113 | | function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure { 6114 | | bytes32 m0; 6115 | | bytes32 m1; 6116 | | bytes32 m2; 6117 | | bytes32 m3; 6118 | | bytes32 m4; 6119 | | bytes32 m5; 6120 | | bytes32 m6; 6121 | | bytes32 m7; 6122 | | bytes32 m8; 6123 | | /// @solidity memory-safe-assembly 6124 | | assembly { 6125 | | function writeString(pos, w) { 6126 | | let length := 0 6127 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6128 | | mstore(pos, length) 6129 | | let shift := sub(256, shl(3, length)) 6130 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6131 | | } 6132 | | m0 := mload(0x00) 6133 | | m1 := mload(0x20) 6134 | | m2 := mload(0x40) 6135 | | m3 := mload(0x60) 6136 | | m4 := mload(0x80) 6137 | | m5 := mload(0xa0) 6138 | | m6 := mload(0xc0) 6139 | | m7 := mload(0xe0) 6140 | | m8 := mload(0x100) 6141 | | // Selector of `log(bool,address,string,string)`. 6142 | | mstore(0x00, 0xa73c1db6) 6143 | | mstore(0x20, p0) 6144 | | mstore(0x40, p1) 6145 | | mstore(0x60, 0x80) 6146 | | mstore(0x80, 0xc0) 6147 | | writeString(0xa0, p2) 6148 | | writeString(0xe0, p3) 6149 | | } 6150 | | _sendLogPayload(0x1c, 0x104); 6151 | | /// @solidity memory-safe-assembly 6152 | | assembly { 6153 | | mstore(0x00, m0) 6154 | | mstore(0x20, m1) 6155 | | mstore(0x40, m2) 6156 | | mstore(0x60, m3) 6157 | | mstore(0x80, m4) 6158 | | mstore(0xa0, m5) 6159 | | mstore(0xc0, m6) 6160 | | mstore(0xe0, m7) 6161 | | mstore(0x100, m8) 6162 | | } 6163 | | } 6164 | | 6165 | | function log(bool p0, bool p1, address p2, address p3) internal pure { 6166 | | bytes32 m0; 6167 | | bytes32 m1; 6168 | | bytes32 m2; 6169 | | bytes32 m3; 6170 | | bytes32 m4; 6171 | | /// @solidity memory-safe-assembly 6172 | | assembly { 6173 | | m0 := mload(0x00) 6174 | | m1 := mload(0x20) 6175 | | m2 := mload(0x40) 6176 | | m3 := mload(0x60) 6177 | | m4 := mload(0x80) 6178 | | // Selector of `log(bool,bool,address,address)`. 6179 | | mstore(0x00, 0xf4880ea4) 6180 | | mstore(0x20, p0) 6181 | | mstore(0x40, p1) 6182 | | mstore(0x60, p2) 6183 | | mstore(0x80, p3) 6184 | | } 6185 | | _sendLogPayload(0x1c, 0x84); 6186 | | /// @solidity memory-safe-assembly 6187 | | assembly { 6188 | | mstore(0x00, m0) 6189 | | mstore(0x20, m1) 6190 | | mstore(0x40, m2) 6191 | | mstore(0x60, m3) 6192 | | mstore(0x80, m4) 6193 | | } 6194 | | } 6195 | | 6196 | | function log(bool p0, bool p1, address p2, bool p3) internal pure { 6197 | | bytes32 m0; 6198 | | bytes32 m1; 6199 | | bytes32 m2; 6200 | | bytes32 m3; 6201 | | bytes32 m4; 6202 | | /// @solidity memory-safe-assembly 6203 | | assembly { 6204 | | m0 := mload(0x00) 6205 | | m1 := mload(0x20) 6206 | | m2 := mload(0x40) 6207 | | m3 := mload(0x60) 6208 | | m4 := mload(0x80) 6209 | | // Selector of `log(bool,bool,address,bool)`. 6210 | | mstore(0x00, 0xc0a302d8) 6211 | | mstore(0x20, p0) 6212 | | mstore(0x40, p1) 6213 | | mstore(0x60, p2) 6214 | | mstore(0x80, p3) 6215 | | } 6216 | | _sendLogPayload(0x1c, 0x84); 6217 | | /// @solidity memory-safe-assembly 6218 | | assembly { 6219 | | mstore(0x00, m0) 6220 | | mstore(0x20, m1) 6221 | | mstore(0x40, m2) 6222 | | mstore(0x60, m3) 6223 | | mstore(0x80, m4) 6224 | | } 6225 | | } 6226 | | 6227 | | function log(bool p0, bool p1, address p2, uint256 p3) internal pure { 6228 | | bytes32 m0; 6229 | | bytes32 m1; 6230 | | bytes32 m2; 6231 | | bytes32 m3; 6232 | | bytes32 m4; 6233 | | /// @solidity memory-safe-assembly 6234 | | assembly { 6235 | | m0 := mload(0x00) 6236 | | m1 := mload(0x20) 6237 | | m2 := mload(0x40) 6238 | | m3 := mload(0x60) 6239 | | m4 := mload(0x80) 6240 | | // Selector of `log(bool,bool,address,uint256)`. 6241 | | mstore(0x00, 0x4c123d57) 6242 | | mstore(0x20, p0) 6243 | | mstore(0x40, p1) 6244 | | mstore(0x60, p2) 6245 | | mstore(0x80, p3) 6246 | | } 6247 | | _sendLogPayload(0x1c, 0x84); 6248 | | /// @solidity memory-safe-assembly 6249 | | assembly { 6250 | | mstore(0x00, m0) 6251 | | mstore(0x20, m1) 6252 | | mstore(0x40, m2) 6253 | | mstore(0x60, m3) 6254 | | mstore(0x80, m4) 6255 | | } 6256 | | } 6257 | | 6258 | | function log(bool p0, bool p1, address p2, bytes32 p3) internal pure { 6259 | | bytes32 m0; 6260 | | bytes32 m1; 6261 | | bytes32 m2; 6262 | | bytes32 m3; 6263 | | bytes32 m4; 6264 | | bytes32 m5; 6265 | | bytes32 m6; 6266 | | /// @solidity memory-safe-assembly 6267 | | assembly { 6268 | | function writeString(pos, w) { 6269 | | let length := 0 6270 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6271 | | mstore(pos, length) 6272 | | let shift := sub(256, shl(3, length)) 6273 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6274 | | } 6275 | | m0 := mload(0x00) 6276 | | m1 := mload(0x20) 6277 | | m2 := mload(0x40) 6278 | | m3 := mload(0x60) 6279 | | m4 := mload(0x80) 6280 | | m5 := mload(0xa0) 6281 | | m6 := mload(0xc0) 6282 | | // Selector of `log(bool,bool,address,string)`. 6283 | | mstore(0x00, 0xa0a47963) 6284 | | mstore(0x20, p0) 6285 | | mstore(0x40, p1) 6286 | | mstore(0x60, p2) 6287 | | mstore(0x80, 0x80) 6288 | | writeString(0xa0, p3) 6289 | | } 6290 | | _sendLogPayload(0x1c, 0xc4); 6291 | | /// @solidity memory-safe-assembly 6292 | | assembly { 6293 | | mstore(0x00, m0) 6294 | | mstore(0x20, m1) 6295 | | mstore(0x40, m2) 6296 | | mstore(0x60, m3) 6297 | | mstore(0x80, m4) 6298 | | mstore(0xa0, m5) 6299 | | mstore(0xc0, m6) 6300 | | } 6301 | | } 6302 | | 6303 | | function log(bool p0, bool p1, bool p2, address p3) internal pure { 6304 | | bytes32 m0; 6305 | | bytes32 m1; 6306 | | bytes32 m2; 6307 | | bytes32 m3; 6308 | | bytes32 m4; 6309 | | /// @solidity memory-safe-assembly 6310 | | assembly { 6311 | | m0 := mload(0x00) 6312 | | m1 := mload(0x20) 6313 | | m2 := mload(0x40) 6314 | | m3 := mload(0x60) 6315 | | m4 := mload(0x80) 6316 | | // Selector of `log(bool,bool,bool,address)`. 6317 | | mstore(0x00, 0x8c329b1a) 6318 | | mstore(0x20, p0) 6319 | | mstore(0x40, p1) 6320 | | mstore(0x60, p2) 6321 | | mstore(0x80, p3) 6322 | | } 6323 | | _sendLogPayload(0x1c, 0x84); 6324 | | /// @solidity memory-safe-assembly 6325 | | assembly { 6326 | | mstore(0x00, m0) 6327 | | mstore(0x20, m1) 6328 | | mstore(0x40, m2) 6329 | | mstore(0x60, m3) 6330 | | mstore(0x80, m4) 6331 | | } 6332 | | } 6333 | | 6334 | | function log(bool p0, bool p1, bool p2, bool p3) internal pure { 6335 | | bytes32 m0; 6336 | | bytes32 m1; 6337 | | bytes32 m2; 6338 | | bytes32 m3; 6339 | | bytes32 m4; 6340 | | /// @solidity memory-safe-assembly 6341 | | assembly { 6342 | | m0 := mload(0x00) 6343 | | m1 := mload(0x20) 6344 | | m2 := mload(0x40) 6345 | | m3 := mload(0x60) 6346 | | m4 := mload(0x80) 6347 | | // Selector of `log(bool,bool,bool,bool)`. 6348 | | mstore(0x00, 0x3b2a5ce0) 6349 | | mstore(0x20, p0) 6350 | | mstore(0x40, p1) 6351 | | mstore(0x60, p2) 6352 | | mstore(0x80, p3) 6353 | | } 6354 | | _sendLogPayload(0x1c, 0x84); 6355 | | /// @solidity memory-safe-assembly 6356 | | assembly { 6357 | | mstore(0x00, m0) 6358 | | mstore(0x20, m1) 6359 | | mstore(0x40, m2) 6360 | | mstore(0x60, m3) 6361 | | mstore(0x80, m4) 6362 | | } 6363 | | } 6364 | | 6365 | | function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { 6366 | | bytes32 m0; 6367 | | bytes32 m1; 6368 | | bytes32 m2; 6369 | | bytes32 m3; 6370 | | bytes32 m4; 6371 | | /// @solidity memory-safe-assembly 6372 | | assembly { 6373 | | m0 := mload(0x00) 6374 | | m1 := mload(0x20) 6375 | | m2 := mload(0x40) 6376 | | m3 := mload(0x60) 6377 | | m4 := mload(0x80) 6378 | | // Selector of `log(bool,bool,bool,uint256)`. 6379 | | mstore(0x00, 0x6d7045c1) 6380 | | mstore(0x20, p0) 6381 | | mstore(0x40, p1) 6382 | | mstore(0x60, p2) 6383 | | mstore(0x80, p3) 6384 | | } 6385 | | _sendLogPayload(0x1c, 0x84); 6386 | | /// @solidity memory-safe-assembly 6387 | | assembly { 6388 | | mstore(0x00, m0) 6389 | | mstore(0x20, m1) 6390 | | mstore(0x40, m2) 6391 | | mstore(0x60, m3) 6392 | | mstore(0x80, m4) 6393 | | } 6394 | | } 6395 | | 6396 | | function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure { 6397 | | bytes32 m0; 6398 | | bytes32 m1; 6399 | | bytes32 m2; 6400 | | bytes32 m3; 6401 | | bytes32 m4; 6402 | | bytes32 m5; 6403 | | bytes32 m6; 6404 | | /// @solidity memory-safe-assembly 6405 | | assembly { 6406 | | function writeString(pos, w) { 6407 | | let length := 0 6408 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6409 | | mstore(pos, length) 6410 | | let shift := sub(256, shl(3, length)) 6411 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6412 | | } 6413 | | m0 := mload(0x00) 6414 | | m1 := mload(0x20) 6415 | | m2 := mload(0x40) 6416 | | m3 := mload(0x60) 6417 | | m4 := mload(0x80) 6418 | | m5 := mload(0xa0) 6419 | | m6 := mload(0xc0) 6420 | | // Selector of `log(bool,bool,bool,string)`. 6421 | | mstore(0x00, 0x2ae408d4) 6422 | | mstore(0x20, p0) 6423 | | mstore(0x40, p1) 6424 | | mstore(0x60, p2) 6425 | | mstore(0x80, 0x80) 6426 | | writeString(0xa0, p3) 6427 | | } 6428 | | _sendLogPayload(0x1c, 0xc4); 6429 | | /// @solidity memory-safe-assembly 6430 | | assembly { 6431 | | mstore(0x00, m0) 6432 | | mstore(0x20, m1) 6433 | | mstore(0x40, m2) 6434 | | mstore(0x60, m3) 6435 | | mstore(0x80, m4) 6436 | | mstore(0xa0, m5) 6437 | | mstore(0xc0, m6) 6438 | | } 6439 | | } 6440 | | 6441 | | function log(bool p0, bool p1, uint256 p2, address p3) internal pure { 6442 | | bytes32 m0; 6443 | | bytes32 m1; 6444 | | bytes32 m2; 6445 | | bytes32 m3; 6446 | | bytes32 m4; 6447 | | /// @solidity memory-safe-assembly 6448 | | assembly { 6449 | | m0 := mload(0x00) 6450 | | m1 := mload(0x20) 6451 | | m2 := mload(0x40) 6452 | | m3 := mload(0x60) 6453 | | m4 := mload(0x80) 6454 | | // Selector of `log(bool,bool,uint256,address)`. 6455 | | mstore(0x00, 0x54a7a9a0) 6456 | | mstore(0x20, p0) 6457 | | mstore(0x40, p1) 6458 | | mstore(0x60, p2) 6459 | | mstore(0x80, p3) 6460 | | } 6461 | | _sendLogPayload(0x1c, 0x84); 6462 | | /// @solidity memory-safe-assembly 6463 | | assembly { 6464 | | mstore(0x00, m0) 6465 | | mstore(0x20, m1) 6466 | | mstore(0x40, m2) 6467 | | mstore(0x60, m3) 6468 | | mstore(0x80, m4) 6469 | | } 6470 | | } 6471 | | 6472 | | function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { 6473 | | bytes32 m0; 6474 | | bytes32 m1; 6475 | | bytes32 m2; 6476 | | bytes32 m3; 6477 | | bytes32 m4; 6478 | | /// @solidity memory-safe-assembly 6479 | | assembly { 6480 | | m0 := mload(0x00) 6481 | | m1 := mload(0x20) 6482 | | m2 := mload(0x40) 6483 | | m3 := mload(0x60) 6484 | | m4 := mload(0x80) 6485 | | // Selector of `log(bool,bool,uint256,bool)`. 6486 | | mstore(0x00, 0x619e4d0e) 6487 | | mstore(0x20, p0) 6488 | | mstore(0x40, p1) 6489 | | mstore(0x60, p2) 6490 | | mstore(0x80, p3) 6491 | | } 6492 | | _sendLogPayload(0x1c, 0x84); 6493 | | /// @solidity memory-safe-assembly 6494 | | assembly { 6495 | | mstore(0x00, m0) 6496 | | mstore(0x20, m1) 6497 | | mstore(0x40, m2) 6498 | | mstore(0x60, m3) 6499 | | mstore(0x80, m4) 6500 | | } 6501 | | } 6502 | | 6503 | | function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { 6504 | | bytes32 m0; 6505 | | bytes32 m1; 6506 | | bytes32 m2; 6507 | | bytes32 m3; 6508 | | bytes32 m4; 6509 | | /// @solidity memory-safe-assembly 6510 | | assembly { 6511 | | m0 := mload(0x00) 6512 | | m1 := mload(0x20) 6513 | | m2 := mload(0x40) 6514 | | m3 := mload(0x60) 6515 | | m4 := mload(0x80) 6516 | | // Selector of `log(bool,bool,uint256,uint256)`. 6517 | | mstore(0x00, 0x0bb00eab) 6518 | | mstore(0x20, p0) 6519 | | mstore(0x40, p1) 6520 | | mstore(0x60, p2) 6521 | | mstore(0x80, p3) 6522 | | } 6523 | | _sendLogPayload(0x1c, 0x84); 6524 | | /// @solidity memory-safe-assembly 6525 | | assembly { 6526 | | mstore(0x00, m0) 6527 | | mstore(0x20, m1) 6528 | | mstore(0x40, m2) 6529 | | mstore(0x60, m3) 6530 | | mstore(0x80, m4) 6531 | | } 6532 | | } 6533 | | 6534 | | function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure { 6535 | | bytes32 m0; 6536 | | bytes32 m1; 6537 | | bytes32 m2; 6538 | | bytes32 m3; 6539 | | bytes32 m4; 6540 | | bytes32 m5; 6541 | | bytes32 m6; 6542 | | /// @solidity memory-safe-assembly 6543 | | assembly { 6544 | | function writeString(pos, w) { 6545 | | let length := 0 6546 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6547 | | mstore(pos, length) 6548 | | let shift := sub(256, shl(3, length)) 6549 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6550 | | } 6551 | | m0 := mload(0x00) 6552 | | m1 := mload(0x20) 6553 | | m2 := mload(0x40) 6554 | | m3 := mload(0x60) 6555 | | m4 := mload(0x80) 6556 | | m5 := mload(0xa0) 6557 | | m6 := mload(0xc0) 6558 | | // Selector of `log(bool,bool,uint256,string)`. 6559 | | mstore(0x00, 0x7dd4d0e0) 6560 | | mstore(0x20, p0) 6561 | | mstore(0x40, p1) 6562 | | mstore(0x60, p2) 6563 | | mstore(0x80, 0x80) 6564 | | writeString(0xa0, p3) 6565 | | } 6566 | | _sendLogPayload(0x1c, 0xc4); 6567 | | /// @solidity memory-safe-assembly 6568 | | assembly { 6569 | | mstore(0x00, m0) 6570 | | mstore(0x20, m1) 6571 | | mstore(0x40, m2) 6572 | | mstore(0x60, m3) 6573 | | mstore(0x80, m4) 6574 | | mstore(0xa0, m5) 6575 | | mstore(0xc0, m6) 6576 | | } 6577 | | } 6578 | | 6579 | | function log(bool p0, bool p1, bytes32 p2, address p3) internal pure { 6580 | | bytes32 m0; 6581 | | bytes32 m1; 6582 | | bytes32 m2; 6583 | | bytes32 m3; 6584 | | bytes32 m4; 6585 | | bytes32 m5; 6586 | | bytes32 m6; 6587 | | /// @solidity memory-safe-assembly 6588 | | assembly { 6589 | | function writeString(pos, w) { 6590 | | let length := 0 6591 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6592 | | mstore(pos, length) 6593 | | let shift := sub(256, shl(3, length)) 6594 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6595 | | } 6596 | | m0 := mload(0x00) 6597 | | m1 := mload(0x20) 6598 | | m2 := mload(0x40) 6599 | | m3 := mload(0x60) 6600 | | m4 := mload(0x80) 6601 | | m5 := mload(0xa0) 6602 | | m6 := mload(0xc0) 6603 | | // Selector of `log(bool,bool,string,address)`. 6604 | | mstore(0x00, 0xf9ad2b89) 6605 | | mstore(0x20, p0) 6606 | | mstore(0x40, p1) 6607 | | mstore(0x60, 0x80) 6608 | | mstore(0x80, p3) 6609 | | writeString(0xa0, p2) 6610 | | } 6611 | | _sendLogPayload(0x1c, 0xc4); 6612 | | /// @solidity memory-safe-assembly 6613 | | assembly { 6614 | | mstore(0x00, m0) 6615 | | mstore(0x20, m1) 6616 | | mstore(0x40, m2) 6617 | | mstore(0x60, m3) 6618 | | mstore(0x80, m4) 6619 | | mstore(0xa0, m5) 6620 | | mstore(0xc0, m6) 6621 | | } 6622 | | } 6623 | | 6624 | | function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure { 6625 | | bytes32 m0; 6626 | | bytes32 m1; 6627 | | bytes32 m2; 6628 | | bytes32 m3; 6629 | | bytes32 m4; 6630 | | bytes32 m5; 6631 | | bytes32 m6; 6632 | | /// @solidity memory-safe-assembly 6633 | | assembly { 6634 | | function writeString(pos, w) { 6635 | | let length := 0 6636 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6637 | | mstore(pos, length) 6638 | | let shift := sub(256, shl(3, length)) 6639 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6640 | | } 6641 | | m0 := mload(0x00) 6642 | | m1 := mload(0x20) 6643 | | m2 := mload(0x40) 6644 | | m3 := mload(0x60) 6645 | | m4 := mload(0x80) 6646 | | m5 := mload(0xa0) 6647 | | m6 := mload(0xc0) 6648 | | // Selector of `log(bool,bool,string,bool)`. 6649 | | mstore(0x00, 0xb857163a) 6650 | | mstore(0x20, p0) 6651 | | mstore(0x40, p1) 6652 | | mstore(0x60, 0x80) 6653 | | mstore(0x80, p3) 6654 | | writeString(0xa0, p2) 6655 | | } 6656 | | _sendLogPayload(0x1c, 0xc4); 6657 | | /// @solidity memory-safe-assembly 6658 | | assembly { 6659 | | mstore(0x00, m0) 6660 | | mstore(0x20, m1) 6661 | | mstore(0x40, m2) 6662 | | mstore(0x60, m3) 6663 | | mstore(0x80, m4) 6664 | | mstore(0xa0, m5) 6665 | | mstore(0xc0, m6) 6666 | | } 6667 | | } 6668 | | 6669 | | function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure { 6670 | | bytes32 m0; 6671 | | bytes32 m1; 6672 | | bytes32 m2; 6673 | | bytes32 m3; 6674 | | bytes32 m4; 6675 | | bytes32 m5; 6676 | | bytes32 m6; 6677 | | /// @solidity memory-safe-assembly 6678 | | assembly { 6679 | | function writeString(pos, w) { 6680 | | let length := 0 6681 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6682 | | mstore(pos, length) 6683 | | let shift := sub(256, shl(3, length)) 6684 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6685 | | } 6686 | | m0 := mload(0x00) 6687 | | m1 := mload(0x20) 6688 | | m2 := mload(0x40) 6689 | | m3 := mload(0x60) 6690 | | m4 := mload(0x80) 6691 | | m5 := mload(0xa0) 6692 | | m6 := mload(0xc0) 6693 | | // Selector of `log(bool,bool,string,uint256)`. 6694 | | mstore(0x00, 0xe3a9ca2f) 6695 | | mstore(0x20, p0) 6696 | | mstore(0x40, p1) 6697 | | mstore(0x60, 0x80) 6698 | | mstore(0x80, p3) 6699 | | writeString(0xa0, p2) 6700 | | } 6701 | | _sendLogPayload(0x1c, 0xc4); 6702 | | /// @solidity memory-safe-assembly 6703 | | assembly { 6704 | | mstore(0x00, m0) 6705 | | mstore(0x20, m1) 6706 | | mstore(0x40, m2) 6707 | | mstore(0x60, m3) 6708 | | mstore(0x80, m4) 6709 | | mstore(0xa0, m5) 6710 | | mstore(0xc0, m6) 6711 | | } 6712 | | } 6713 | | 6714 | | function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure { 6715 | | bytes32 m0; 6716 | | bytes32 m1; 6717 | | bytes32 m2; 6718 | | bytes32 m3; 6719 | | bytes32 m4; 6720 | | bytes32 m5; 6721 | | bytes32 m6; 6722 | | bytes32 m7; 6723 | | bytes32 m8; 6724 | | /// @solidity memory-safe-assembly 6725 | | assembly { 6726 | | function writeString(pos, w) { 6727 | | let length := 0 6728 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6729 | | mstore(pos, length) 6730 | | let shift := sub(256, shl(3, length)) 6731 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6732 | | } 6733 | | m0 := mload(0x00) 6734 | | m1 := mload(0x20) 6735 | | m2 := mload(0x40) 6736 | | m3 := mload(0x60) 6737 | | m4 := mload(0x80) 6738 | | m5 := mload(0xa0) 6739 | | m6 := mload(0xc0) 6740 | | m7 := mload(0xe0) 6741 | | m8 := mload(0x100) 6742 | | // Selector of `log(bool,bool,string,string)`. 6743 | | mstore(0x00, 0x6d1e8751) 6744 | | mstore(0x20, p0) 6745 | | mstore(0x40, p1) 6746 | | mstore(0x60, 0x80) 6747 | | mstore(0x80, 0xc0) 6748 | | writeString(0xa0, p2) 6749 | | writeString(0xe0, p3) 6750 | | } 6751 | | _sendLogPayload(0x1c, 0x104); 6752 | | /// @solidity memory-safe-assembly 6753 | | assembly { 6754 | | mstore(0x00, m0) 6755 | | mstore(0x20, m1) 6756 | | mstore(0x40, m2) 6757 | | mstore(0x60, m3) 6758 | | mstore(0x80, m4) 6759 | | mstore(0xa0, m5) 6760 | | mstore(0xc0, m6) 6761 | | mstore(0xe0, m7) 6762 | | mstore(0x100, m8) 6763 | | } 6764 | | } 6765 | | 6766 | | function log(bool p0, uint256 p1, address p2, address p3) internal pure { 6767 | | bytes32 m0; 6768 | | bytes32 m1; 6769 | | bytes32 m2; 6770 | | bytes32 m3; 6771 | | bytes32 m4; 6772 | | /// @solidity memory-safe-assembly 6773 | | assembly { 6774 | | m0 := mload(0x00) 6775 | | m1 := mload(0x20) 6776 | | m2 := mload(0x40) 6777 | | m3 := mload(0x60) 6778 | | m4 := mload(0x80) 6779 | | // Selector of `log(bool,uint256,address,address)`. 6780 | | mstore(0x00, 0x26f560a8) 6781 | | mstore(0x20, p0) 6782 | | mstore(0x40, p1) 6783 | | mstore(0x60, p2) 6784 | | mstore(0x80, p3) 6785 | | } 6786 | | _sendLogPayload(0x1c, 0x84); 6787 | | /// @solidity memory-safe-assembly 6788 | | assembly { 6789 | | mstore(0x00, m0) 6790 | | mstore(0x20, m1) 6791 | | mstore(0x40, m2) 6792 | | mstore(0x60, m3) 6793 | | mstore(0x80, m4) 6794 | | } 6795 | | } 6796 | | 6797 | | function log(bool p0, uint256 p1, address p2, bool p3) internal pure { 6798 | | bytes32 m0; 6799 | | bytes32 m1; 6800 | | bytes32 m2; 6801 | | bytes32 m3; 6802 | | bytes32 m4; 6803 | | /// @solidity memory-safe-assembly 6804 | | assembly { 6805 | | m0 := mload(0x00) 6806 | | m1 := mload(0x20) 6807 | | m2 := mload(0x40) 6808 | | m3 := mload(0x60) 6809 | | m4 := mload(0x80) 6810 | | // Selector of `log(bool,uint256,address,bool)`. 6811 | | mstore(0x00, 0xb4c314ff) 6812 | | mstore(0x20, p0) 6813 | | mstore(0x40, p1) 6814 | | mstore(0x60, p2) 6815 | | mstore(0x80, p3) 6816 | | } 6817 | | _sendLogPayload(0x1c, 0x84); 6818 | | /// @solidity memory-safe-assembly 6819 | | assembly { 6820 | | mstore(0x00, m0) 6821 | | mstore(0x20, m1) 6822 | | mstore(0x40, m2) 6823 | | mstore(0x60, m3) 6824 | | mstore(0x80, m4) 6825 | | } 6826 | | } 6827 | | 6828 | | function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { 6829 | | bytes32 m0; 6830 | | bytes32 m1; 6831 | | bytes32 m2; 6832 | | bytes32 m3; 6833 | | bytes32 m4; 6834 | | /// @solidity memory-safe-assembly 6835 | | assembly { 6836 | | m0 := mload(0x00) 6837 | | m1 := mload(0x20) 6838 | | m2 := mload(0x40) 6839 | | m3 := mload(0x60) 6840 | | m4 := mload(0x80) 6841 | | // Selector of `log(bool,uint256,address,uint256)`. 6842 | | mstore(0x00, 0x1537dc87) 6843 | | mstore(0x20, p0) 6844 | | mstore(0x40, p1) 6845 | | mstore(0x60, p2) 6846 | | mstore(0x80, p3) 6847 | | } 6848 | | _sendLogPayload(0x1c, 0x84); 6849 | | /// @solidity memory-safe-assembly 6850 | | assembly { 6851 | | mstore(0x00, m0) 6852 | | mstore(0x20, m1) 6853 | | mstore(0x40, m2) 6854 | | mstore(0x60, m3) 6855 | | mstore(0x80, m4) 6856 | | } 6857 | | } 6858 | | 6859 | | function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure { 6860 | | bytes32 m0; 6861 | | bytes32 m1; 6862 | | bytes32 m2; 6863 | | bytes32 m3; 6864 | | bytes32 m4; 6865 | | bytes32 m5; 6866 | | bytes32 m6; 6867 | | /// @solidity memory-safe-assembly 6868 | | assembly { 6869 | | function writeString(pos, w) { 6870 | | let length := 0 6871 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 6872 | | mstore(pos, length) 6873 | | let shift := sub(256, shl(3, length)) 6874 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 6875 | | } 6876 | | m0 := mload(0x00) 6877 | | m1 := mload(0x20) 6878 | | m2 := mload(0x40) 6879 | | m3 := mload(0x60) 6880 | | m4 := mload(0x80) 6881 | | m5 := mload(0xa0) 6882 | | m6 := mload(0xc0) 6883 | | // Selector of `log(bool,uint256,address,string)`. 6884 | | mstore(0x00, 0x1bb3b09a) 6885 | | mstore(0x20, p0) 6886 | | mstore(0x40, p1) 6887 | | mstore(0x60, p2) 6888 | | mstore(0x80, 0x80) 6889 | | writeString(0xa0, p3) 6890 | | } 6891 | | _sendLogPayload(0x1c, 0xc4); 6892 | | /// @solidity memory-safe-assembly 6893 | | assembly { 6894 | | mstore(0x00, m0) 6895 | | mstore(0x20, m1) 6896 | | mstore(0x40, m2) 6897 | | mstore(0x60, m3) 6898 | | mstore(0x80, m4) 6899 | | mstore(0xa0, m5) 6900 | | mstore(0xc0, m6) 6901 | | } 6902 | | } 6903 | | 6904 | | function log(bool p0, uint256 p1, bool p2, address p3) internal pure { 6905 | | bytes32 m0; 6906 | | bytes32 m1; 6907 | | bytes32 m2; 6908 | | bytes32 m3; 6909 | | bytes32 m4; 6910 | | /// @solidity memory-safe-assembly 6911 | | assembly { 6912 | | m0 := mload(0x00) 6913 | | m1 := mload(0x20) 6914 | | m2 := mload(0x40) 6915 | | m3 := mload(0x60) 6916 | | m4 := mload(0x80) 6917 | | // Selector of `log(bool,uint256,bool,address)`. 6918 | | mstore(0x00, 0x9acd3616) 6919 | | mstore(0x20, p0) 6920 | | mstore(0x40, p1) 6921 | | mstore(0x60, p2) 6922 | | mstore(0x80, p3) 6923 | | } 6924 | | _sendLogPayload(0x1c, 0x84); 6925 | | /// @solidity memory-safe-assembly 6926 | | assembly { 6927 | | mstore(0x00, m0) 6928 | | mstore(0x20, m1) 6929 | | mstore(0x40, m2) 6930 | | mstore(0x60, m3) 6931 | | mstore(0x80, m4) 6932 | | } 6933 | | } 6934 | | 6935 | | function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { 6936 | | bytes32 m0; 6937 | | bytes32 m1; 6938 | | bytes32 m2; 6939 | | bytes32 m3; 6940 | | bytes32 m4; 6941 | | /// @solidity memory-safe-assembly 6942 | | assembly { 6943 | | m0 := mload(0x00) 6944 | | m1 := mload(0x20) 6945 | | m2 := mload(0x40) 6946 | | m3 := mload(0x60) 6947 | | m4 := mload(0x80) 6948 | | // Selector of `log(bool,uint256,bool,bool)`. 6949 | | mstore(0x00, 0xceb5f4d7) 6950 | | mstore(0x20, p0) 6951 | | mstore(0x40, p1) 6952 | | mstore(0x60, p2) 6953 | | mstore(0x80, p3) 6954 | | } 6955 | | _sendLogPayload(0x1c, 0x84); 6956 | | /// @solidity memory-safe-assembly 6957 | | assembly { 6958 | | mstore(0x00, m0) 6959 | | mstore(0x20, m1) 6960 | | mstore(0x40, m2) 6961 | | mstore(0x60, m3) 6962 | | mstore(0x80, m4) 6963 | | } 6964 | | } 6965 | | 6966 | | function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { 6967 | | bytes32 m0; 6968 | | bytes32 m1; 6969 | | bytes32 m2; 6970 | | bytes32 m3; 6971 | | bytes32 m4; 6972 | | /// @solidity memory-safe-assembly 6973 | | assembly { 6974 | | m0 := mload(0x00) 6975 | | m1 := mload(0x20) 6976 | | m2 := mload(0x40) 6977 | | m3 := mload(0x60) 6978 | | m4 := mload(0x80) 6979 | | // Selector of `log(bool,uint256,bool,uint256)`. 6980 | | mstore(0x00, 0x7f9bbca2) 6981 | | mstore(0x20, p0) 6982 | | mstore(0x40, p1) 6983 | | mstore(0x60, p2) 6984 | | mstore(0x80, p3) 6985 | | } 6986 | | _sendLogPayload(0x1c, 0x84); 6987 | | /// @solidity memory-safe-assembly 6988 | | assembly { 6989 | | mstore(0x00, m0) 6990 | | mstore(0x20, m1) 6991 | | mstore(0x40, m2) 6992 | | mstore(0x60, m3) 6993 | | mstore(0x80, m4) 6994 | | } 6995 | | } 6996 | | 6997 | | function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure { 6998 | | bytes32 m0; 6999 | | bytes32 m1; 7000 | | bytes32 m2; 7001 | | bytes32 m3; 7002 | | bytes32 m4; 7003 | | bytes32 m5; 7004 | | bytes32 m6; 7005 | | /// @solidity memory-safe-assembly 7006 | | assembly { 7007 | | function writeString(pos, w) { 7008 | | let length := 0 7009 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7010 | | mstore(pos, length) 7011 | | let shift := sub(256, shl(3, length)) 7012 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7013 | | } 7014 | | m0 := mload(0x00) 7015 | | m1 := mload(0x20) 7016 | | m2 := mload(0x40) 7017 | | m3 := mload(0x60) 7018 | | m4 := mload(0x80) 7019 | | m5 := mload(0xa0) 7020 | | m6 := mload(0xc0) 7021 | | // Selector of `log(bool,uint256,bool,string)`. 7022 | | mstore(0x00, 0x9143dbb1) 7023 | | mstore(0x20, p0) 7024 | | mstore(0x40, p1) 7025 | | mstore(0x60, p2) 7026 | | mstore(0x80, 0x80) 7027 | | writeString(0xa0, p3) 7028 | | } 7029 | | _sendLogPayload(0x1c, 0xc4); 7030 | | /// @solidity memory-safe-assembly 7031 | | assembly { 7032 | | mstore(0x00, m0) 7033 | | mstore(0x20, m1) 7034 | | mstore(0x40, m2) 7035 | | mstore(0x60, m3) 7036 | | mstore(0x80, m4) 7037 | | mstore(0xa0, m5) 7038 | | mstore(0xc0, m6) 7039 | | } 7040 | | } 7041 | | 7042 | | function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { 7043 | | bytes32 m0; 7044 | | bytes32 m1; 7045 | | bytes32 m2; 7046 | | bytes32 m3; 7047 | | bytes32 m4; 7048 | | /// @solidity memory-safe-assembly 7049 | | assembly { 7050 | | m0 := mload(0x00) 7051 | | m1 := mload(0x20) 7052 | | m2 := mload(0x40) 7053 | | m3 := mload(0x60) 7054 | | m4 := mload(0x80) 7055 | | // Selector of `log(bool,uint256,uint256,address)`. 7056 | | mstore(0x00, 0x00dd87b9) 7057 | | mstore(0x20, p0) 7058 | | mstore(0x40, p1) 7059 | | mstore(0x60, p2) 7060 | | mstore(0x80, p3) 7061 | | } 7062 | | _sendLogPayload(0x1c, 0x84); 7063 | | /// @solidity memory-safe-assembly 7064 | | assembly { 7065 | | mstore(0x00, m0) 7066 | | mstore(0x20, m1) 7067 | | mstore(0x40, m2) 7068 | | mstore(0x60, m3) 7069 | | mstore(0x80, m4) 7070 | | } 7071 | | } 7072 | | 7073 | | function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { 7074 | | bytes32 m0; 7075 | | bytes32 m1; 7076 | | bytes32 m2; 7077 | | bytes32 m3; 7078 | | bytes32 m4; 7079 | | /// @solidity memory-safe-assembly 7080 | | assembly { 7081 | | m0 := mload(0x00) 7082 | | m1 := mload(0x20) 7083 | | m2 := mload(0x40) 7084 | | m3 := mload(0x60) 7085 | | m4 := mload(0x80) 7086 | | // Selector of `log(bool,uint256,uint256,bool)`. 7087 | | mstore(0x00, 0xbe984353) 7088 | | mstore(0x20, p0) 7089 | | mstore(0x40, p1) 7090 | | mstore(0x60, p2) 7091 | | mstore(0x80, p3) 7092 | | } 7093 | | _sendLogPayload(0x1c, 0x84); 7094 | | /// @solidity memory-safe-assembly 7095 | | assembly { 7096 | | mstore(0x00, m0) 7097 | | mstore(0x20, m1) 7098 | | mstore(0x40, m2) 7099 | | mstore(0x60, m3) 7100 | | mstore(0x80, m4) 7101 | | } 7102 | | } 7103 | | 7104 | | function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 7105 | | bytes32 m0; 7106 | | bytes32 m1; 7107 | | bytes32 m2; 7108 | | bytes32 m3; 7109 | | bytes32 m4; 7110 | | /// @solidity memory-safe-assembly 7111 | | assembly { 7112 | | m0 := mload(0x00) 7113 | | m1 := mload(0x20) 7114 | | m2 := mload(0x40) 7115 | | m3 := mload(0x60) 7116 | | m4 := mload(0x80) 7117 | | // Selector of `log(bool,uint256,uint256,uint256)`. 7118 | | mstore(0x00, 0x374bb4b2) 7119 | | mstore(0x20, p0) 7120 | | mstore(0x40, p1) 7121 | | mstore(0x60, p2) 7122 | | mstore(0x80, p3) 7123 | | } 7124 | | _sendLogPayload(0x1c, 0x84); 7125 | | /// @solidity memory-safe-assembly 7126 | | assembly { 7127 | | mstore(0x00, m0) 7128 | | mstore(0x20, m1) 7129 | | mstore(0x40, m2) 7130 | | mstore(0x60, m3) 7131 | | mstore(0x80, m4) 7132 | | } 7133 | | } 7134 | | 7135 | | function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { 7136 | | bytes32 m0; 7137 | | bytes32 m1; 7138 | | bytes32 m2; 7139 | | bytes32 m3; 7140 | | bytes32 m4; 7141 | | bytes32 m5; 7142 | | bytes32 m6; 7143 | | /// @solidity memory-safe-assembly 7144 | | assembly { 7145 | | function writeString(pos, w) { 7146 | | let length := 0 7147 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7148 | | mstore(pos, length) 7149 | | let shift := sub(256, shl(3, length)) 7150 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7151 | | } 7152 | | m0 := mload(0x00) 7153 | | m1 := mload(0x20) 7154 | | m2 := mload(0x40) 7155 | | m3 := mload(0x60) 7156 | | m4 := mload(0x80) 7157 | | m5 := mload(0xa0) 7158 | | m6 := mload(0xc0) 7159 | | // Selector of `log(bool,uint256,uint256,string)`. 7160 | | mstore(0x00, 0x8e69fb5d) 7161 | | mstore(0x20, p0) 7162 | | mstore(0x40, p1) 7163 | | mstore(0x60, p2) 7164 | | mstore(0x80, 0x80) 7165 | | writeString(0xa0, p3) 7166 | | } 7167 | | _sendLogPayload(0x1c, 0xc4); 7168 | | /// @solidity memory-safe-assembly 7169 | | assembly { 7170 | | mstore(0x00, m0) 7171 | | mstore(0x20, m1) 7172 | | mstore(0x40, m2) 7173 | | mstore(0x60, m3) 7174 | | mstore(0x80, m4) 7175 | | mstore(0xa0, m5) 7176 | | mstore(0xc0, m6) 7177 | | } 7178 | | } 7179 | | 7180 | | function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure { 7181 | | bytes32 m0; 7182 | | bytes32 m1; 7183 | | bytes32 m2; 7184 | | bytes32 m3; 7185 | | bytes32 m4; 7186 | | bytes32 m5; 7187 | | bytes32 m6; 7188 | | /// @solidity memory-safe-assembly 7189 | | assembly { 7190 | | function writeString(pos, w) { 7191 | | let length := 0 7192 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7193 | | mstore(pos, length) 7194 | | let shift := sub(256, shl(3, length)) 7195 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7196 | | } 7197 | | m0 := mload(0x00) 7198 | | m1 := mload(0x20) 7199 | | m2 := mload(0x40) 7200 | | m3 := mload(0x60) 7201 | | m4 := mload(0x80) 7202 | | m5 := mload(0xa0) 7203 | | m6 := mload(0xc0) 7204 | | // Selector of `log(bool,uint256,string,address)`. 7205 | | mstore(0x00, 0xfedd1fff) 7206 | | mstore(0x20, p0) 7207 | | mstore(0x40, p1) 7208 | | mstore(0x60, 0x80) 7209 | | mstore(0x80, p3) 7210 | | writeString(0xa0, p2) 7211 | | } 7212 | | _sendLogPayload(0x1c, 0xc4); 7213 | | /// @solidity memory-safe-assembly 7214 | | assembly { 7215 | | mstore(0x00, m0) 7216 | | mstore(0x20, m1) 7217 | | mstore(0x40, m2) 7218 | | mstore(0x60, m3) 7219 | | mstore(0x80, m4) 7220 | | mstore(0xa0, m5) 7221 | | mstore(0xc0, m6) 7222 | | } 7223 | | } 7224 | | 7225 | | function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure { 7226 | | bytes32 m0; 7227 | | bytes32 m1; 7228 | | bytes32 m2; 7229 | | bytes32 m3; 7230 | | bytes32 m4; 7231 | | bytes32 m5; 7232 | | bytes32 m6; 7233 | | /// @solidity memory-safe-assembly 7234 | | assembly { 7235 | | function writeString(pos, w) { 7236 | | let length := 0 7237 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7238 | | mstore(pos, length) 7239 | | let shift := sub(256, shl(3, length)) 7240 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7241 | | } 7242 | | m0 := mload(0x00) 7243 | | m1 := mload(0x20) 7244 | | m2 := mload(0x40) 7245 | | m3 := mload(0x60) 7246 | | m4 := mload(0x80) 7247 | | m5 := mload(0xa0) 7248 | | m6 := mload(0xc0) 7249 | | // Selector of `log(bool,uint256,string,bool)`. 7250 | | mstore(0x00, 0xe5e70b2b) 7251 | | mstore(0x20, p0) 7252 | | mstore(0x40, p1) 7253 | | mstore(0x60, 0x80) 7254 | | mstore(0x80, p3) 7255 | | writeString(0xa0, p2) 7256 | | } 7257 | | _sendLogPayload(0x1c, 0xc4); 7258 | | /// @solidity memory-safe-assembly 7259 | | assembly { 7260 | | mstore(0x00, m0) 7261 | | mstore(0x20, m1) 7262 | | mstore(0x40, m2) 7263 | | mstore(0x60, m3) 7264 | | mstore(0x80, m4) 7265 | | mstore(0xa0, m5) 7266 | | mstore(0xc0, m6) 7267 | | } 7268 | | } 7269 | | 7270 | | function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { 7271 | | bytes32 m0; 7272 | | bytes32 m1; 7273 | | bytes32 m2; 7274 | | bytes32 m3; 7275 | | bytes32 m4; 7276 | | bytes32 m5; 7277 | | bytes32 m6; 7278 | | /// @solidity memory-safe-assembly 7279 | | assembly { 7280 | | function writeString(pos, w) { 7281 | | let length := 0 7282 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7283 | | mstore(pos, length) 7284 | | let shift := sub(256, shl(3, length)) 7285 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7286 | | } 7287 | | m0 := mload(0x00) 7288 | | m1 := mload(0x20) 7289 | | m2 := mload(0x40) 7290 | | m3 := mload(0x60) 7291 | | m4 := mload(0x80) 7292 | | m5 := mload(0xa0) 7293 | | m6 := mload(0xc0) 7294 | | // Selector of `log(bool,uint256,string,uint256)`. 7295 | | mstore(0x00, 0x6a1199e2) 7296 | | mstore(0x20, p0) 7297 | | mstore(0x40, p1) 7298 | | mstore(0x60, 0x80) 7299 | | mstore(0x80, p3) 7300 | | writeString(0xa0, p2) 7301 | | } 7302 | | _sendLogPayload(0x1c, 0xc4); 7303 | | /// @solidity memory-safe-assembly 7304 | | assembly { 7305 | | mstore(0x00, m0) 7306 | | mstore(0x20, m1) 7307 | | mstore(0x40, m2) 7308 | | mstore(0x60, m3) 7309 | | mstore(0x80, m4) 7310 | | mstore(0xa0, m5) 7311 | | mstore(0xc0, m6) 7312 | | } 7313 | | } 7314 | | 7315 | | function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { 7316 | | bytes32 m0; 7317 | | bytes32 m1; 7318 | | bytes32 m2; 7319 | | bytes32 m3; 7320 | | bytes32 m4; 7321 | | bytes32 m5; 7322 | | bytes32 m6; 7323 | | bytes32 m7; 7324 | | bytes32 m8; 7325 | | /// @solidity memory-safe-assembly 7326 | | assembly { 7327 | | function writeString(pos, w) { 7328 | | let length := 0 7329 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7330 | | mstore(pos, length) 7331 | | let shift := sub(256, shl(3, length)) 7332 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7333 | | } 7334 | | m0 := mload(0x00) 7335 | | m1 := mload(0x20) 7336 | | m2 := mload(0x40) 7337 | | m3 := mload(0x60) 7338 | | m4 := mload(0x80) 7339 | | m5 := mload(0xa0) 7340 | | m6 := mload(0xc0) 7341 | | m7 := mload(0xe0) 7342 | | m8 := mload(0x100) 7343 | | // Selector of `log(bool,uint256,string,string)`. 7344 | | mstore(0x00, 0xf5bc2249) 7345 | | mstore(0x20, p0) 7346 | | mstore(0x40, p1) 7347 | | mstore(0x60, 0x80) 7348 | | mstore(0x80, 0xc0) 7349 | | writeString(0xa0, p2) 7350 | | writeString(0xe0, p3) 7351 | | } 7352 | | _sendLogPayload(0x1c, 0x104); 7353 | | /// @solidity memory-safe-assembly 7354 | | assembly { 7355 | | mstore(0x00, m0) 7356 | | mstore(0x20, m1) 7357 | | mstore(0x40, m2) 7358 | | mstore(0x60, m3) 7359 | | mstore(0x80, m4) 7360 | | mstore(0xa0, m5) 7361 | | mstore(0xc0, m6) 7362 | | mstore(0xe0, m7) 7363 | | mstore(0x100, m8) 7364 | | } 7365 | | } 7366 | | 7367 | | function log(bool p0, bytes32 p1, address p2, address p3) internal pure { 7368 | | bytes32 m0; 7369 | | bytes32 m1; 7370 | | bytes32 m2; 7371 | | bytes32 m3; 7372 | | bytes32 m4; 7373 | | bytes32 m5; 7374 | | bytes32 m6; 7375 | | /// @solidity memory-safe-assembly 7376 | | assembly { 7377 | | function writeString(pos, w) { 7378 | | let length := 0 7379 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7380 | | mstore(pos, length) 7381 | | let shift := sub(256, shl(3, length)) 7382 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7383 | | } 7384 | | m0 := mload(0x00) 7385 | | m1 := mload(0x20) 7386 | | m2 := mload(0x40) 7387 | | m3 := mload(0x60) 7388 | | m4 := mload(0x80) 7389 | | m5 := mload(0xa0) 7390 | | m6 := mload(0xc0) 7391 | | // Selector of `log(bool,string,address,address)`. 7392 | | mstore(0x00, 0x2b2b18dc) 7393 | | mstore(0x20, p0) 7394 | | mstore(0x40, 0x80) 7395 | | mstore(0x60, p2) 7396 | | mstore(0x80, p3) 7397 | | writeString(0xa0, p1) 7398 | | } 7399 | | _sendLogPayload(0x1c, 0xc4); 7400 | | /// @solidity memory-safe-assembly 7401 | | assembly { 7402 | | mstore(0x00, m0) 7403 | | mstore(0x20, m1) 7404 | | mstore(0x40, m2) 7405 | | mstore(0x60, m3) 7406 | | mstore(0x80, m4) 7407 | | mstore(0xa0, m5) 7408 | | mstore(0xc0, m6) 7409 | | } 7410 | | } 7411 | | 7412 | | function log(bool p0, bytes32 p1, address p2, bool p3) internal pure { 7413 | | bytes32 m0; 7414 | | bytes32 m1; 7415 | | bytes32 m2; 7416 | | bytes32 m3; 7417 | | bytes32 m4; 7418 | | bytes32 m5; 7419 | | bytes32 m6; 7420 | | /// @solidity memory-safe-assembly 7421 | | assembly { 7422 | | function writeString(pos, w) { 7423 | | let length := 0 7424 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7425 | | mstore(pos, length) 7426 | | let shift := sub(256, shl(3, length)) 7427 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7428 | | } 7429 | | m0 := mload(0x00) 7430 | | m1 := mload(0x20) 7431 | | m2 := mload(0x40) 7432 | | m3 := mload(0x60) 7433 | | m4 := mload(0x80) 7434 | | m5 := mload(0xa0) 7435 | | m6 := mload(0xc0) 7436 | | // Selector of `log(bool,string,address,bool)`. 7437 | | mstore(0x00, 0x6dd434ca) 7438 | | mstore(0x20, p0) 7439 | | mstore(0x40, 0x80) 7440 | | mstore(0x60, p2) 7441 | | mstore(0x80, p3) 7442 | | writeString(0xa0, p1) 7443 | | } 7444 | | _sendLogPayload(0x1c, 0xc4); 7445 | | /// @solidity memory-safe-assembly 7446 | | assembly { 7447 | | mstore(0x00, m0) 7448 | | mstore(0x20, m1) 7449 | | mstore(0x40, m2) 7450 | | mstore(0x60, m3) 7451 | | mstore(0x80, m4) 7452 | | mstore(0xa0, m5) 7453 | | mstore(0xc0, m6) 7454 | | } 7455 | | } 7456 | | 7457 | | function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure { 7458 | | bytes32 m0; 7459 | | bytes32 m1; 7460 | | bytes32 m2; 7461 | | bytes32 m3; 7462 | | bytes32 m4; 7463 | | bytes32 m5; 7464 | | bytes32 m6; 7465 | | /// @solidity memory-safe-assembly 7466 | | assembly { 7467 | | function writeString(pos, w) { 7468 | | let length := 0 7469 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7470 | | mstore(pos, length) 7471 | | let shift := sub(256, shl(3, length)) 7472 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7473 | | } 7474 | | m0 := mload(0x00) 7475 | | m1 := mload(0x20) 7476 | | m2 := mload(0x40) 7477 | | m3 := mload(0x60) 7478 | | m4 := mload(0x80) 7479 | | m5 := mload(0xa0) 7480 | | m6 := mload(0xc0) 7481 | | // Selector of `log(bool,string,address,uint256)`. 7482 | | mstore(0x00, 0xa5cada94) 7483 | | mstore(0x20, p0) 7484 | | mstore(0x40, 0x80) 7485 | | mstore(0x60, p2) 7486 | | mstore(0x80, p3) 7487 | | writeString(0xa0, p1) 7488 | | } 7489 | | _sendLogPayload(0x1c, 0xc4); 7490 | | /// @solidity memory-safe-assembly 7491 | | assembly { 7492 | | mstore(0x00, m0) 7493 | | mstore(0x20, m1) 7494 | | mstore(0x40, m2) 7495 | | mstore(0x60, m3) 7496 | | mstore(0x80, m4) 7497 | | mstore(0xa0, m5) 7498 | | mstore(0xc0, m6) 7499 | | } 7500 | | } 7501 | | 7502 | | function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure { 7503 | | bytes32 m0; 7504 | | bytes32 m1; 7505 | | bytes32 m2; 7506 | | bytes32 m3; 7507 | | bytes32 m4; 7508 | | bytes32 m5; 7509 | | bytes32 m6; 7510 | | bytes32 m7; 7511 | | bytes32 m8; 7512 | | /// @solidity memory-safe-assembly 7513 | | assembly { 7514 | | function writeString(pos, w) { 7515 | | let length := 0 7516 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7517 | | mstore(pos, length) 7518 | | let shift := sub(256, shl(3, length)) 7519 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7520 | | } 7521 | | m0 := mload(0x00) 7522 | | m1 := mload(0x20) 7523 | | m2 := mload(0x40) 7524 | | m3 := mload(0x60) 7525 | | m4 := mload(0x80) 7526 | | m5 := mload(0xa0) 7527 | | m6 := mload(0xc0) 7528 | | m7 := mload(0xe0) 7529 | | m8 := mload(0x100) 7530 | | // Selector of `log(bool,string,address,string)`. 7531 | | mstore(0x00, 0x12d6c788) 7532 | | mstore(0x20, p0) 7533 | | mstore(0x40, 0x80) 7534 | | mstore(0x60, p2) 7535 | | mstore(0x80, 0xc0) 7536 | | writeString(0xa0, p1) 7537 | | writeString(0xe0, p3) 7538 | | } 7539 | | _sendLogPayload(0x1c, 0x104); 7540 | | /// @solidity memory-safe-assembly 7541 | | assembly { 7542 | | mstore(0x00, m0) 7543 | | mstore(0x20, m1) 7544 | | mstore(0x40, m2) 7545 | | mstore(0x60, m3) 7546 | | mstore(0x80, m4) 7547 | | mstore(0xa0, m5) 7548 | | mstore(0xc0, m6) 7549 | | mstore(0xe0, m7) 7550 | | mstore(0x100, m8) 7551 | | } 7552 | | } 7553 | | 7554 | | function log(bool p0, bytes32 p1, bool p2, address p3) internal pure { 7555 | | bytes32 m0; 7556 | | bytes32 m1; 7557 | | bytes32 m2; 7558 | | bytes32 m3; 7559 | | bytes32 m4; 7560 | | bytes32 m5; 7561 | | bytes32 m6; 7562 | | /// @solidity memory-safe-assembly 7563 | | assembly { 7564 | | function writeString(pos, w) { 7565 | | let length := 0 7566 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7567 | | mstore(pos, length) 7568 | | let shift := sub(256, shl(3, length)) 7569 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7570 | | } 7571 | | m0 := mload(0x00) 7572 | | m1 := mload(0x20) 7573 | | m2 := mload(0x40) 7574 | | m3 := mload(0x60) 7575 | | m4 := mload(0x80) 7576 | | m5 := mload(0xa0) 7577 | | m6 := mload(0xc0) 7578 | | // Selector of `log(bool,string,bool,address)`. 7579 | | mstore(0x00, 0x538e06ab) 7580 | | mstore(0x20, p0) 7581 | | mstore(0x40, 0x80) 7582 | | mstore(0x60, p2) 7583 | | mstore(0x80, p3) 7584 | | writeString(0xa0, p1) 7585 | | } 7586 | | _sendLogPayload(0x1c, 0xc4); 7587 | | /// @solidity memory-safe-assembly 7588 | | assembly { 7589 | | mstore(0x00, m0) 7590 | | mstore(0x20, m1) 7591 | | mstore(0x40, m2) 7592 | | mstore(0x60, m3) 7593 | | mstore(0x80, m4) 7594 | | mstore(0xa0, m5) 7595 | | mstore(0xc0, m6) 7596 | | } 7597 | | } 7598 | | 7599 | | function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure { 7600 | | bytes32 m0; 7601 | | bytes32 m1; 7602 | | bytes32 m2; 7603 | | bytes32 m3; 7604 | | bytes32 m4; 7605 | | bytes32 m5; 7606 | | bytes32 m6; 7607 | | /// @solidity memory-safe-assembly 7608 | | assembly { 7609 | | function writeString(pos, w) { 7610 | | let length := 0 7611 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7612 | | mstore(pos, length) 7613 | | let shift := sub(256, shl(3, length)) 7614 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7615 | | } 7616 | | m0 := mload(0x00) 7617 | | m1 := mload(0x20) 7618 | | m2 := mload(0x40) 7619 | | m3 := mload(0x60) 7620 | | m4 := mload(0x80) 7621 | | m5 := mload(0xa0) 7622 | | m6 := mload(0xc0) 7623 | | // Selector of `log(bool,string,bool,bool)`. 7624 | | mstore(0x00, 0xdc5e935b) 7625 | | mstore(0x20, p0) 7626 | | mstore(0x40, 0x80) 7627 | | mstore(0x60, p2) 7628 | | mstore(0x80, p3) 7629 | | writeString(0xa0, p1) 7630 | | } 7631 | | _sendLogPayload(0x1c, 0xc4); 7632 | | /// @solidity memory-safe-assembly 7633 | | assembly { 7634 | | mstore(0x00, m0) 7635 | | mstore(0x20, m1) 7636 | | mstore(0x40, m2) 7637 | | mstore(0x60, m3) 7638 | | mstore(0x80, m4) 7639 | | mstore(0xa0, m5) 7640 | | mstore(0xc0, m6) 7641 | | } 7642 | | } 7643 | | 7644 | | function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure { 7645 | | bytes32 m0; 7646 | | bytes32 m1; 7647 | | bytes32 m2; 7648 | | bytes32 m3; 7649 | | bytes32 m4; 7650 | | bytes32 m5; 7651 | | bytes32 m6; 7652 | | /// @solidity memory-safe-assembly 7653 | | assembly { 7654 | | function writeString(pos, w) { 7655 | | let length := 0 7656 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7657 | | mstore(pos, length) 7658 | | let shift := sub(256, shl(3, length)) 7659 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7660 | | } 7661 | | m0 := mload(0x00) 7662 | | m1 := mload(0x20) 7663 | | m2 := mload(0x40) 7664 | | m3 := mload(0x60) 7665 | | m4 := mload(0x80) 7666 | | m5 := mload(0xa0) 7667 | | m6 := mload(0xc0) 7668 | | // Selector of `log(bool,string,bool,uint256)`. 7669 | | mstore(0x00, 0x1606a393) 7670 | | mstore(0x20, p0) 7671 | | mstore(0x40, 0x80) 7672 | | mstore(0x60, p2) 7673 | | mstore(0x80, p3) 7674 | | writeString(0xa0, p1) 7675 | | } 7676 | | _sendLogPayload(0x1c, 0xc4); 7677 | | /// @solidity memory-safe-assembly 7678 | | assembly { 7679 | | mstore(0x00, m0) 7680 | | mstore(0x20, m1) 7681 | | mstore(0x40, m2) 7682 | | mstore(0x60, m3) 7683 | | mstore(0x80, m4) 7684 | | mstore(0xa0, m5) 7685 | | mstore(0xc0, m6) 7686 | | } 7687 | | } 7688 | | 7689 | | function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure { 7690 | | bytes32 m0; 7691 | | bytes32 m1; 7692 | | bytes32 m2; 7693 | | bytes32 m3; 7694 | | bytes32 m4; 7695 | | bytes32 m5; 7696 | | bytes32 m6; 7697 | | bytes32 m7; 7698 | | bytes32 m8; 7699 | | /// @solidity memory-safe-assembly 7700 | | assembly { 7701 | | function writeString(pos, w) { 7702 | | let length := 0 7703 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7704 | | mstore(pos, length) 7705 | | let shift := sub(256, shl(3, length)) 7706 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7707 | | } 7708 | | m0 := mload(0x00) 7709 | | m1 := mload(0x20) 7710 | | m2 := mload(0x40) 7711 | | m3 := mload(0x60) 7712 | | m4 := mload(0x80) 7713 | | m5 := mload(0xa0) 7714 | | m6 := mload(0xc0) 7715 | | m7 := mload(0xe0) 7716 | | m8 := mload(0x100) 7717 | | // Selector of `log(bool,string,bool,string)`. 7718 | | mstore(0x00, 0x483d0416) 7719 | | mstore(0x20, p0) 7720 | | mstore(0x40, 0x80) 7721 | | mstore(0x60, p2) 7722 | | mstore(0x80, 0xc0) 7723 | | writeString(0xa0, p1) 7724 | | writeString(0xe0, p3) 7725 | | } 7726 | | _sendLogPayload(0x1c, 0x104); 7727 | | /// @solidity memory-safe-assembly 7728 | | assembly { 7729 | | mstore(0x00, m0) 7730 | | mstore(0x20, m1) 7731 | | mstore(0x40, m2) 7732 | | mstore(0x60, m3) 7733 | | mstore(0x80, m4) 7734 | | mstore(0xa0, m5) 7735 | | mstore(0xc0, m6) 7736 | | mstore(0xe0, m7) 7737 | | mstore(0x100, m8) 7738 | | } 7739 | | } 7740 | | 7741 | | function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure { 7742 | | bytes32 m0; 7743 | | bytes32 m1; 7744 | | bytes32 m2; 7745 | | bytes32 m3; 7746 | | bytes32 m4; 7747 | | bytes32 m5; 7748 | | bytes32 m6; 7749 | | /// @solidity memory-safe-assembly 7750 | | assembly { 7751 | | function writeString(pos, w) { 7752 | | let length := 0 7753 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7754 | | mstore(pos, length) 7755 | | let shift := sub(256, shl(3, length)) 7756 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7757 | | } 7758 | | m0 := mload(0x00) 7759 | | m1 := mload(0x20) 7760 | | m2 := mload(0x40) 7761 | | m3 := mload(0x60) 7762 | | m4 := mload(0x80) 7763 | | m5 := mload(0xa0) 7764 | | m6 := mload(0xc0) 7765 | | // Selector of `log(bool,string,uint256,address)`. 7766 | | mstore(0x00, 0x1596a1ce) 7767 | | mstore(0x20, p0) 7768 | | mstore(0x40, 0x80) 7769 | | mstore(0x60, p2) 7770 | | mstore(0x80, p3) 7771 | | writeString(0xa0, p1) 7772 | | } 7773 | | _sendLogPayload(0x1c, 0xc4); 7774 | | /// @solidity memory-safe-assembly 7775 | | assembly { 7776 | | mstore(0x00, m0) 7777 | | mstore(0x20, m1) 7778 | | mstore(0x40, m2) 7779 | | mstore(0x60, m3) 7780 | | mstore(0x80, m4) 7781 | | mstore(0xa0, m5) 7782 | | mstore(0xc0, m6) 7783 | | } 7784 | | } 7785 | | 7786 | | function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure { 7787 | | bytes32 m0; 7788 | | bytes32 m1; 7789 | | bytes32 m2; 7790 | | bytes32 m3; 7791 | | bytes32 m4; 7792 | | bytes32 m5; 7793 | | bytes32 m6; 7794 | | /// @solidity memory-safe-assembly 7795 | | assembly { 7796 | | function writeString(pos, w) { 7797 | | let length := 0 7798 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7799 | | mstore(pos, length) 7800 | | let shift := sub(256, shl(3, length)) 7801 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7802 | | } 7803 | | m0 := mload(0x00) 7804 | | m1 := mload(0x20) 7805 | | m2 := mload(0x40) 7806 | | m3 := mload(0x60) 7807 | | m4 := mload(0x80) 7808 | | m5 := mload(0xa0) 7809 | | m6 := mload(0xc0) 7810 | | // Selector of `log(bool,string,uint256,bool)`. 7811 | | mstore(0x00, 0x6b0e5d53) 7812 | | mstore(0x20, p0) 7813 | | mstore(0x40, 0x80) 7814 | | mstore(0x60, p2) 7815 | | mstore(0x80, p3) 7816 | | writeString(0xa0, p1) 7817 | | } 7818 | | _sendLogPayload(0x1c, 0xc4); 7819 | | /// @solidity memory-safe-assembly 7820 | | assembly { 7821 | | mstore(0x00, m0) 7822 | | mstore(0x20, m1) 7823 | | mstore(0x40, m2) 7824 | | mstore(0x60, m3) 7825 | | mstore(0x80, m4) 7826 | | mstore(0xa0, m5) 7827 | | mstore(0xc0, m6) 7828 | | } 7829 | | } 7830 | | 7831 | | function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { 7832 | | bytes32 m0; 7833 | | bytes32 m1; 7834 | | bytes32 m2; 7835 | | bytes32 m3; 7836 | | bytes32 m4; 7837 | | bytes32 m5; 7838 | | bytes32 m6; 7839 | | /// @solidity memory-safe-assembly 7840 | | assembly { 7841 | | function writeString(pos, w) { 7842 | | let length := 0 7843 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7844 | | mstore(pos, length) 7845 | | let shift := sub(256, shl(3, length)) 7846 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7847 | | } 7848 | | m0 := mload(0x00) 7849 | | m1 := mload(0x20) 7850 | | m2 := mload(0x40) 7851 | | m3 := mload(0x60) 7852 | | m4 := mload(0x80) 7853 | | m5 := mload(0xa0) 7854 | | m6 := mload(0xc0) 7855 | | // Selector of `log(bool,string,uint256,uint256)`. 7856 | | mstore(0x00, 0x28863fcb) 7857 | | mstore(0x20, p0) 7858 | | mstore(0x40, 0x80) 7859 | | mstore(0x60, p2) 7860 | | mstore(0x80, p3) 7861 | | writeString(0xa0, p1) 7862 | | } 7863 | | _sendLogPayload(0x1c, 0xc4); 7864 | | /// @solidity memory-safe-assembly 7865 | | assembly { 7866 | | mstore(0x00, m0) 7867 | | mstore(0x20, m1) 7868 | | mstore(0x40, m2) 7869 | | mstore(0x60, m3) 7870 | | mstore(0x80, m4) 7871 | | mstore(0xa0, m5) 7872 | | mstore(0xc0, m6) 7873 | | } 7874 | | } 7875 | | 7876 | | function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { 7877 | | bytes32 m0; 7878 | | bytes32 m1; 7879 | | bytes32 m2; 7880 | | bytes32 m3; 7881 | | bytes32 m4; 7882 | | bytes32 m5; 7883 | | bytes32 m6; 7884 | | bytes32 m7; 7885 | | bytes32 m8; 7886 | | /// @solidity memory-safe-assembly 7887 | | assembly { 7888 | | function writeString(pos, w) { 7889 | | let length := 0 7890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7891 | | mstore(pos, length) 7892 | | let shift := sub(256, shl(3, length)) 7893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7894 | | } 7895 | | m0 := mload(0x00) 7896 | | m1 := mload(0x20) 7897 | | m2 := mload(0x40) 7898 | | m3 := mload(0x60) 7899 | | m4 := mload(0x80) 7900 | | m5 := mload(0xa0) 7901 | | m6 := mload(0xc0) 7902 | | m7 := mload(0xe0) 7903 | | m8 := mload(0x100) 7904 | | // Selector of `log(bool,string,uint256,string)`. 7905 | | mstore(0x00, 0x1ad96de6) 7906 | | mstore(0x20, p0) 7907 | | mstore(0x40, 0x80) 7908 | | mstore(0x60, p2) 7909 | | mstore(0x80, 0xc0) 7910 | | writeString(0xa0, p1) 7911 | | writeString(0xe0, p3) 7912 | | } 7913 | | _sendLogPayload(0x1c, 0x104); 7914 | | /// @solidity memory-safe-assembly 7915 | | assembly { 7916 | | mstore(0x00, m0) 7917 | | mstore(0x20, m1) 7918 | | mstore(0x40, m2) 7919 | | mstore(0x60, m3) 7920 | | mstore(0x80, m4) 7921 | | mstore(0xa0, m5) 7922 | | mstore(0xc0, m6) 7923 | | mstore(0xe0, m7) 7924 | | mstore(0x100, m8) 7925 | | } 7926 | | } 7927 | | 7928 | | function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure { 7929 | | bytes32 m0; 7930 | | bytes32 m1; 7931 | | bytes32 m2; 7932 | | bytes32 m3; 7933 | | bytes32 m4; 7934 | | bytes32 m5; 7935 | | bytes32 m6; 7936 | | bytes32 m7; 7937 | | bytes32 m8; 7938 | | /// @solidity memory-safe-assembly 7939 | | assembly { 7940 | | function writeString(pos, w) { 7941 | | let length := 0 7942 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7943 | | mstore(pos, length) 7944 | | let shift := sub(256, shl(3, length)) 7945 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7946 | | } 7947 | | m0 := mload(0x00) 7948 | | m1 := mload(0x20) 7949 | | m2 := mload(0x40) 7950 | | m3 := mload(0x60) 7951 | | m4 := mload(0x80) 7952 | | m5 := mload(0xa0) 7953 | | m6 := mload(0xc0) 7954 | | m7 := mload(0xe0) 7955 | | m8 := mload(0x100) 7956 | | // Selector of `log(bool,string,string,address)`. 7957 | | mstore(0x00, 0x97d394d8) 7958 | | mstore(0x20, p0) 7959 | | mstore(0x40, 0x80) 7960 | | mstore(0x60, 0xc0) 7961 | | mstore(0x80, p3) 7962 | | writeString(0xa0, p1) 7963 | | writeString(0xe0, p2) 7964 | | } 7965 | | _sendLogPayload(0x1c, 0x104); 7966 | | /// @solidity memory-safe-assembly 7967 | | assembly { 7968 | | mstore(0x00, m0) 7969 | | mstore(0x20, m1) 7970 | | mstore(0x40, m2) 7971 | | mstore(0x60, m3) 7972 | | mstore(0x80, m4) 7973 | | mstore(0xa0, m5) 7974 | | mstore(0xc0, m6) 7975 | | mstore(0xe0, m7) 7976 | | mstore(0x100, m8) 7977 | | } 7978 | | } 7979 | | 7980 | | function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure { 7981 | | bytes32 m0; 7982 | | bytes32 m1; 7983 | | bytes32 m2; 7984 | | bytes32 m3; 7985 | | bytes32 m4; 7986 | | bytes32 m5; 7987 | | bytes32 m6; 7988 | | bytes32 m7; 7989 | | bytes32 m8; 7990 | | /// @solidity memory-safe-assembly 7991 | | assembly { 7992 | | function writeString(pos, w) { 7993 | | let length := 0 7994 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 7995 | | mstore(pos, length) 7996 | | let shift := sub(256, shl(3, length)) 7997 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 7998 | | } 7999 | | m0 := mload(0x00) 8000 | | m1 := mload(0x20) 8001 | | m2 := mload(0x40) 8002 | | m3 := mload(0x60) 8003 | | m4 := mload(0x80) 8004 | | m5 := mload(0xa0) 8005 | | m6 := mload(0xc0) 8006 | | m7 := mload(0xe0) 8007 | | m8 := mload(0x100) 8008 | | // Selector of `log(bool,string,string,bool)`. 8009 | | mstore(0x00, 0x1e4b87e5) 8010 | | mstore(0x20, p0) 8011 | | mstore(0x40, 0x80) 8012 | | mstore(0x60, 0xc0) 8013 | | mstore(0x80, p3) 8014 | | writeString(0xa0, p1) 8015 | | writeString(0xe0, p2) 8016 | | } 8017 | | _sendLogPayload(0x1c, 0x104); 8018 | | /// @solidity memory-safe-assembly 8019 | | assembly { 8020 | | mstore(0x00, m0) 8021 | | mstore(0x20, m1) 8022 | | mstore(0x40, m2) 8023 | | mstore(0x60, m3) 8024 | | mstore(0x80, m4) 8025 | | mstore(0xa0, m5) 8026 | | mstore(0xc0, m6) 8027 | | mstore(0xe0, m7) 8028 | | mstore(0x100, m8) 8029 | | } 8030 | | } 8031 | | 8032 | | function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { 8033 | | bytes32 m0; 8034 | | bytes32 m1; 8035 | | bytes32 m2; 8036 | | bytes32 m3; 8037 | | bytes32 m4; 8038 | | bytes32 m5; 8039 | | bytes32 m6; 8040 | | bytes32 m7; 8041 | | bytes32 m8; 8042 | | /// @solidity memory-safe-assembly 8043 | | assembly { 8044 | | function writeString(pos, w) { 8045 | | let length := 0 8046 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8047 | | mstore(pos, length) 8048 | | let shift := sub(256, shl(3, length)) 8049 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8050 | | } 8051 | | m0 := mload(0x00) 8052 | | m1 := mload(0x20) 8053 | | m2 := mload(0x40) 8054 | | m3 := mload(0x60) 8055 | | m4 := mload(0x80) 8056 | | m5 := mload(0xa0) 8057 | | m6 := mload(0xc0) 8058 | | m7 := mload(0xe0) 8059 | | m8 := mload(0x100) 8060 | | // Selector of `log(bool,string,string,uint256)`. 8061 | | mstore(0x00, 0x7be0c3eb) 8062 | | mstore(0x20, p0) 8063 | | mstore(0x40, 0x80) 8064 | | mstore(0x60, 0xc0) 8065 | | mstore(0x80, p3) 8066 | | writeString(0xa0, p1) 8067 | | writeString(0xe0, p2) 8068 | | } 8069 | | _sendLogPayload(0x1c, 0x104); 8070 | | /// @solidity memory-safe-assembly 8071 | | assembly { 8072 | | mstore(0x00, m0) 8073 | | mstore(0x20, m1) 8074 | | mstore(0x40, m2) 8075 | | mstore(0x60, m3) 8076 | | mstore(0x80, m4) 8077 | | mstore(0xa0, m5) 8078 | | mstore(0xc0, m6) 8079 | | mstore(0xe0, m7) 8080 | | mstore(0x100, m8) 8081 | | } 8082 | | } 8083 | | 8084 | | function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { 8085 | | bytes32 m0; 8086 | | bytes32 m1; 8087 | | bytes32 m2; 8088 | | bytes32 m3; 8089 | | bytes32 m4; 8090 | | bytes32 m5; 8091 | | bytes32 m6; 8092 | | bytes32 m7; 8093 | | bytes32 m8; 8094 | | bytes32 m9; 8095 | | bytes32 m10; 8096 | | /// @solidity memory-safe-assembly 8097 | | assembly { 8098 | | function writeString(pos, w) { 8099 | | let length := 0 8100 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8101 | | mstore(pos, length) 8102 | | let shift := sub(256, shl(3, length)) 8103 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8104 | | } 8105 | | m0 := mload(0x00) 8106 | | m1 := mload(0x20) 8107 | | m2 := mload(0x40) 8108 | | m3 := mload(0x60) 8109 | | m4 := mload(0x80) 8110 | | m5 := mload(0xa0) 8111 | | m6 := mload(0xc0) 8112 | | m7 := mload(0xe0) 8113 | | m8 := mload(0x100) 8114 | | m9 := mload(0x120) 8115 | | m10 := mload(0x140) 8116 | | // Selector of `log(bool,string,string,string)`. 8117 | | mstore(0x00, 0x1762e32a) 8118 | | mstore(0x20, p0) 8119 | | mstore(0x40, 0x80) 8120 | | mstore(0x60, 0xc0) 8121 | | mstore(0x80, 0x100) 8122 | | writeString(0xa0, p1) 8123 | | writeString(0xe0, p2) 8124 | | writeString(0x120, p3) 8125 | | } 8126 | | _sendLogPayload(0x1c, 0x144); 8127 | | /// @solidity memory-safe-assembly 8128 | | assembly { 8129 | | mstore(0x00, m0) 8130 | | mstore(0x20, m1) 8131 | | mstore(0x40, m2) 8132 | | mstore(0x60, m3) 8133 | | mstore(0x80, m4) 8134 | | mstore(0xa0, m5) 8135 | | mstore(0xc0, m6) 8136 | | mstore(0xe0, m7) 8137 | | mstore(0x100, m8) 8138 | | mstore(0x120, m9) 8139 | | mstore(0x140, m10) 8140 | | } 8141 | | } 8142 | | 8143 | | function log(uint256 p0, address p1, address p2, address p3) internal pure { 8144 | | bytes32 m0; 8145 | | bytes32 m1; 8146 | | bytes32 m2; 8147 | | bytes32 m3; 8148 | | bytes32 m4; 8149 | | /// @solidity memory-safe-assembly 8150 | | assembly { 8151 | | m0 := mload(0x00) 8152 | | m1 := mload(0x20) 8153 | | m2 := mload(0x40) 8154 | | m3 := mload(0x60) 8155 | | m4 := mload(0x80) 8156 | | // Selector of `log(uint256,address,address,address)`. 8157 | | mstore(0x00, 0x2488b414) 8158 | | mstore(0x20, p0) 8159 | | mstore(0x40, p1) 8160 | | mstore(0x60, p2) 8161 | | mstore(0x80, p3) 8162 | | } 8163 | | _sendLogPayload(0x1c, 0x84); 8164 | | /// @solidity memory-safe-assembly 8165 | | assembly { 8166 | | mstore(0x00, m0) 8167 | | mstore(0x20, m1) 8168 | | mstore(0x40, m2) 8169 | | mstore(0x60, m3) 8170 | | mstore(0x80, m4) 8171 | | } 8172 | | } 8173 | | 8174 | | function log(uint256 p0, address p1, address p2, bool p3) internal pure { 8175 | | bytes32 m0; 8176 | | bytes32 m1; 8177 | | bytes32 m2; 8178 | | bytes32 m3; 8179 | | bytes32 m4; 8180 | | /// @solidity memory-safe-assembly 8181 | | assembly { 8182 | | m0 := mload(0x00) 8183 | | m1 := mload(0x20) 8184 | | m2 := mload(0x40) 8185 | | m3 := mload(0x60) 8186 | | m4 := mload(0x80) 8187 | | // Selector of `log(uint256,address,address,bool)`. 8188 | | mstore(0x00, 0x091ffaf5) 8189 | | mstore(0x20, p0) 8190 | | mstore(0x40, p1) 8191 | | mstore(0x60, p2) 8192 | | mstore(0x80, p3) 8193 | | } 8194 | | _sendLogPayload(0x1c, 0x84); 8195 | | /// @solidity memory-safe-assembly 8196 | | assembly { 8197 | | mstore(0x00, m0) 8198 | | mstore(0x20, m1) 8199 | | mstore(0x40, m2) 8200 | | mstore(0x60, m3) 8201 | | mstore(0x80, m4) 8202 | | } 8203 | | } 8204 | | 8205 | | function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { 8206 | | bytes32 m0; 8207 | | bytes32 m1; 8208 | | bytes32 m2; 8209 | | bytes32 m3; 8210 | | bytes32 m4; 8211 | | /// @solidity memory-safe-assembly 8212 | | assembly { 8213 | | m0 := mload(0x00) 8214 | | m1 := mload(0x20) 8215 | | m2 := mload(0x40) 8216 | | m3 := mload(0x60) 8217 | | m4 := mload(0x80) 8218 | | // Selector of `log(uint256,address,address,uint256)`. 8219 | | mstore(0x00, 0x736efbb6) 8220 | | mstore(0x20, p0) 8221 | | mstore(0x40, p1) 8222 | | mstore(0x60, p2) 8223 | | mstore(0x80, p3) 8224 | | } 8225 | | _sendLogPayload(0x1c, 0x84); 8226 | | /// @solidity memory-safe-assembly 8227 | | assembly { 8228 | | mstore(0x00, m0) 8229 | | mstore(0x20, m1) 8230 | | mstore(0x40, m2) 8231 | | mstore(0x60, m3) 8232 | | mstore(0x80, m4) 8233 | | } 8234 | | } 8235 | | 8236 | | function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure { 8237 | | bytes32 m0; 8238 | | bytes32 m1; 8239 | | bytes32 m2; 8240 | | bytes32 m3; 8241 | | bytes32 m4; 8242 | | bytes32 m5; 8243 | | bytes32 m6; 8244 | | /// @solidity memory-safe-assembly 8245 | | assembly { 8246 | | function writeString(pos, w) { 8247 | | let length := 0 8248 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8249 | | mstore(pos, length) 8250 | | let shift := sub(256, shl(3, length)) 8251 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8252 | | } 8253 | | m0 := mload(0x00) 8254 | | m1 := mload(0x20) 8255 | | m2 := mload(0x40) 8256 | | m3 := mload(0x60) 8257 | | m4 := mload(0x80) 8258 | | m5 := mload(0xa0) 8259 | | m6 := mload(0xc0) 8260 | | // Selector of `log(uint256,address,address,string)`. 8261 | | mstore(0x00, 0x031c6f73) 8262 | | mstore(0x20, p0) 8263 | | mstore(0x40, p1) 8264 | | mstore(0x60, p2) 8265 | | mstore(0x80, 0x80) 8266 | | writeString(0xa0, p3) 8267 | | } 8268 | | _sendLogPayload(0x1c, 0xc4); 8269 | | /// @solidity memory-safe-assembly 8270 | | assembly { 8271 | | mstore(0x00, m0) 8272 | | mstore(0x20, m1) 8273 | | mstore(0x40, m2) 8274 | | mstore(0x60, m3) 8275 | | mstore(0x80, m4) 8276 | | mstore(0xa0, m5) 8277 | | mstore(0xc0, m6) 8278 | | } 8279 | | } 8280 | | 8281 | | function log(uint256 p0, address p1, bool p2, address p3) internal pure { 8282 | | bytes32 m0; 8283 | | bytes32 m1; 8284 | | bytes32 m2; 8285 | | bytes32 m3; 8286 | | bytes32 m4; 8287 | | /// @solidity memory-safe-assembly 8288 | | assembly { 8289 | | m0 := mload(0x00) 8290 | | m1 := mload(0x20) 8291 | | m2 := mload(0x40) 8292 | | m3 := mload(0x60) 8293 | | m4 := mload(0x80) 8294 | | // Selector of `log(uint256,address,bool,address)`. 8295 | | mstore(0x00, 0xef72c513) 8296 | | mstore(0x20, p0) 8297 | | mstore(0x40, p1) 8298 | | mstore(0x60, p2) 8299 | | mstore(0x80, p3) 8300 | | } 8301 | | _sendLogPayload(0x1c, 0x84); 8302 | | /// @solidity memory-safe-assembly 8303 | | assembly { 8304 | | mstore(0x00, m0) 8305 | | mstore(0x20, m1) 8306 | | mstore(0x40, m2) 8307 | | mstore(0x60, m3) 8308 | | mstore(0x80, m4) 8309 | | } 8310 | | } 8311 | | 8312 | | function log(uint256 p0, address p1, bool p2, bool p3) internal pure { 8313 | | bytes32 m0; 8314 | | bytes32 m1; 8315 | | bytes32 m2; 8316 | | bytes32 m3; 8317 | | bytes32 m4; 8318 | | /// @solidity memory-safe-assembly 8319 | | assembly { 8320 | | m0 := mload(0x00) 8321 | | m1 := mload(0x20) 8322 | | m2 := mload(0x40) 8323 | | m3 := mload(0x60) 8324 | | m4 := mload(0x80) 8325 | | // Selector of `log(uint256,address,bool,bool)`. 8326 | | mstore(0x00, 0xe351140f) 8327 | | mstore(0x20, p0) 8328 | | mstore(0x40, p1) 8329 | | mstore(0x60, p2) 8330 | | mstore(0x80, p3) 8331 | | } 8332 | | _sendLogPayload(0x1c, 0x84); 8333 | | /// @solidity memory-safe-assembly 8334 | | assembly { 8335 | | mstore(0x00, m0) 8336 | | mstore(0x20, m1) 8337 | | mstore(0x40, m2) 8338 | | mstore(0x60, m3) 8339 | | mstore(0x80, m4) 8340 | | } 8341 | | } 8342 | | 8343 | | function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { 8344 | | bytes32 m0; 8345 | | bytes32 m1; 8346 | | bytes32 m2; 8347 | | bytes32 m3; 8348 | | bytes32 m4; 8349 | | /// @solidity memory-safe-assembly 8350 | | assembly { 8351 | | m0 := mload(0x00) 8352 | | m1 := mload(0x20) 8353 | | m2 := mload(0x40) 8354 | | m3 := mload(0x60) 8355 | | m4 := mload(0x80) 8356 | | // Selector of `log(uint256,address,bool,uint256)`. 8357 | | mstore(0x00, 0x5abd992a) 8358 | | mstore(0x20, p0) 8359 | | mstore(0x40, p1) 8360 | | mstore(0x60, p2) 8361 | | mstore(0x80, p3) 8362 | | } 8363 | | _sendLogPayload(0x1c, 0x84); 8364 | | /// @solidity memory-safe-assembly 8365 | | assembly { 8366 | | mstore(0x00, m0) 8367 | | mstore(0x20, m1) 8368 | | mstore(0x40, m2) 8369 | | mstore(0x60, m3) 8370 | | mstore(0x80, m4) 8371 | | } 8372 | | } 8373 | | 8374 | | function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure { 8375 | | bytes32 m0; 8376 | | bytes32 m1; 8377 | | bytes32 m2; 8378 | | bytes32 m3; 8379 | | bytes32 m4; 8380 | | bytes32 m5; 8381 | | bytes32 m6; 8382 | | /// @solidity memory-safe-assembly 8383 | | assembly { 8384 | | function writeString(pos, w) { 8385 | | let length := 0 8386 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8387 | | mstore(pos, length) 8388 | | let shift := sub(256, shl(3, length)) 8389 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8390 | | } 8391 | | m0 := mload(0x00) 8392 | | m1 := mload(0x20) 8393 | | m2 := mload(0x40) 8394 | | m3 := mload(0x60) 8395 | | m4 := mload(0x80) 8396 | | m5 := mload(0xa0) 8397 | | m6 := mload(0xc0) 8398 | | // Selector of `log(uint256,address,bool,string)`. 8399 | | mstore(0x00, 0x90fb06aa) 8400 | | mstore(0x20, p0) 8401 | | mstore(0x40, p1) 8402 | | mstore(0x60, p2) 8403 | | mstore(0x80, 0x80) 8404 | | writeString(0xa0, p3) 8405 | | } 8406 | | _sendLogPayload(0x1c, 0xc4); 8407 | | /// @solidity memory-safe-assembly 8408 | | assembly { 8409 | | mstore(0x00, m0) 8410 | | mstore(0x20, m1) 8411 | | mstore(0x40, m2) 8412 | | mstore(0x60, m3) 8413 | | mstore(0x80, m4) 8414 | | mstore(0xa0, m5) 8415 | | mstore(0xc0, m6) 8416 | | } 8417 | | } 8418 | | 8419 | | function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { 8420 | | bytes32 m0; 8421 | | bytes32 m1; 8422 | | bytes32 m2; 8423 | | bytes32 m3; 8424 | | bytes32 m4; 8425 | | /// @solidity memory-safe-assembly 8426 | | assembly { 8427 | | m0 := mload(0x00) 8428 | | m1 := mload(0x20) 8429 | | m2 := mload(0x40) 8430 | | m3 := mload(0x60) 8431 | | m4 := mload(0x80) 8432 | | // Selector of `log(uint256,address,uint256,address)`. 8433 | | mstore(0x00, 0x15c127b5) 8434 | | mstore(0x20, p0) 8435 | | mstore(0x40, p1) 8436 | | mstore(0x60, p2) 8437 | | mstore(0x80, p3) 8438 | | } 8439 | | _sendLogPayload(0x1c, 0x84); 8440 | | /// @solidity memory-safe-assembly 8441 | | assembly { 8442 | | mstore(0x00, m0) 8443 | | mstore(0x20, m1) 8444 | | mstore(0x40, m2) 8445 | | mstore(0x60, m3) 8446 | | mstore(0x80, m4) 8447 | | } 8448 | | } 8449 | | 8450 | | function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { 8451 | | bytes32 m0; 8452 | | bytes32 m1; 8453 | | bytes32 m2; 8454 | | bytes32 m3; 8455 | | bytes32 m4; 8456 | | /// @solidity memory-safe-assembly 8457 | | assembly { 8458 | | m0 := mload(0x00) 8459 | | m1 := mload(0x20) 8460 | | m2 := mload(0x40) 8461 | | m3 := mload(0x60) 8462 | | m4 := mload(0x80) 8463 | | // Selector of `log(uint256,address,uint256,bool)`. 8464 | | mstore(0x00, 0x5f743a7c) 8465 | | mstore(0x20, p0) 8466 | | mstore(0x40, p1) 8467 | | mstore(0x60, p2) 8468 | | mstore(0x80, p3) 8469 | | } 8470 | | _sendLogPayload(0x1c, 0x84); 8471 | | /// @solidity memory-safe-assembly 8472 | | assembly { 8473 | | mstore(0x00, m0) 8474 | | mstore(0x20, m1) 8475 | | mstore(0x40, m2) 8476 | | mstore(0x60, m3) 8477 | | mstore(0x80, m4) 8478 | | } 8479 | | } 8480 | | 8481 | | function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { 8482 | | bytes32 m0; 8483 | | bytes32 m1; 8484 | | bytes32 m2; 8485 | | bytes32 m3; 8486 | | bytes32 m4; 8487 | | /// @solidity memory-safe-assembly 8488 | | assembly { 8489 | | m0 := mload(0x00) 8490 | | m1 := mload(0x20) 8491 | | m2 := mload(0x40) 8492 | | m3 := mload(0x60) 8493 | | m4 := mload(0x80) 8494 | | // Selector of `log(uint256,address,uint256,uint256)`. 8495 | | mstore(0x00, 0x0c9cd9c1) 8496 | | mstore(0x20, p0) 8497 | | mstore(0x40, p1) 8498 | | mstore(0x60, p2) 8499 | | mstore(0x80, p3) 8500 | | } 8501 | | _sendLogPayload(0x1c, 0x84); 8502 | | /// @solidity memory-safe-assembly 8503 | | assembly { 8504 | | mstore(0x00, m0) 8505 | | mstore(0x20, m1) 8506 | | mstore(0x40, m2) 8507 | | mstore(0x60, m3) 8508 | | mstore(0x80, m4) 8509 | | } 8510 | | } 8511 | | 8512 | | function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure { 8513 | | bytes32 m0; 8514 | | bytes32 m1; 8515 | | bytes32 m2; 8516 | | bytes32 m3; 8517 | | bytes32 m4; 8518 | | bytes32 m5; 8519 | | bytes32 m6; 8520 | | /// @solidity memory-safe-assembly 8521 | | assembly { 8522 | | function writeString(pos, w) { 8523 | | let length := 0 8524 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8525 | | mstore(pos, length) 8526 | | let shift := sub(256, shl(3, length)) 8527 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8528 | | } 8529 | | m0 := mload(0x00) 8530 | | m1 := mload(0x20) 8531 | | m2 := mload(0x40) 8532 | | m3 := mload(0x60) 8533 | | m4 := mload(0x80) 8534 | | m5 := mload(0xa0) 8535 | | m6 := mload(0xc0) 8536 | | // Selector of `log(uint256,address,uint256,string)`. 8537 | | mstore(0x00, 0xddb06521) 8538 | | mstore(0x20, p0) 8539 | | mstore(0x40, p1) 8540 | | mstore(0x60, p2) 8541 | | mstore(0x80, 0x80) 8542 | | writeString(0xa0, p3) 8543 | | } 8544 | | _sendLogPayload(0x1c, 0xc4); 8545 | | /// @solidity memory-safe-assembly 8546 | | assembly { 8547 | | mstore(0x00, m0) 8548 | | mstore(0x20, m1) 8549 | | mstore(0x40, m2) 8550 | | mstore(0x60, m3) 8551 | | mstore(0x80, m4) 8552 | | mstore(0xa0, m5) 8553 | | mstore(0xc0, m6) 8554 | | } 8555 | | } 8556 | | 8557 | | function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure { 8558 | | bytes32 m0; 8559 | | bytes32 m1; 8560 | | bytes32 m2; 8561 | | bytes32 m3; 8562 | | bytes32 m4; 8563 | | bytes32 m5; 8564 | | bytes32 m6; 8565 | | /// @solidity memory-safe-assembly 8566 | | assembly { 8567 | | function writeString(pos, w) { 8568 | | let length := 0 8569 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8570 | | mstore(pos, length) 8571 | | let shift := sub(256, shl(3, length)) 8572 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8573 | | } 8574 | | m0 := mload(0x00) 8575 | | m1 := mload(0x20) 8576 | | m2 := mload(0x40) 8577 | | m3 := mload(0x60) 8578 | | m4 := mload(0x80) 8579 | | m5 := mload(0xa0) 8580 | | m6 := mload(0xc0) 8581 | | // Selector of `log(uint256,address,string,address)`. 8582 | | mstore(0x00, 0x9cba8fff) 8583 | | mstore(0x20, p0) 8584 | | mstore(0x40, p1) 8585 | | mstore(0x60, 0x80) 8586 | | mstore(0x80, p3) 8587 | | writeString(0xa0, p2) 8588 | | } 8589 | | _sendLogPayload(0x1c, 0xc4); 8590 | | /// @solidity memory-safe-assembly 8591 | | assembly { 8592 | | mstore(0x00, m0) 8593 | | mstore(0x20, m1) 8594 | | mstore(0x40, m2) 8595 | | mstore(0x60, m3) 8596 | | mstore(0x80, m4) 8597 | | mstore(0xa0, m5) 8598 | | mstore(0xc0, m6) 8599 | | } 8600 | | } 8601 | | 8602 | | function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure { 8603 | | bytes32 m0; 8604 | | bytes32 m1; 8605 | | bytes32 m2; 8606 | | bytes32 m3; 8607 | | bytes32 m4; 8608 | | bytes32 m5; 8609 | | bytes32 m6; 8610 | | /// @solidity memory-safe-assembly 8611 | | assembly { 8612 | | function writeString(pos, w) { 8613 | | let length := 0 8614 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8615 | | mstore(pos, length) 8616 | | let shift := sub(256, shl(3, length)) 8617 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8618 | | } 8619 | | m0 := mload(0x00) 8620 | | m1 := mload(0x20) 8621 | | m2 := mload(0x40) 8622 | | m3 := mload(0x60) 8623 | | m4 := mload(0x80) 8624 | | m5 := mload(0xa0) 8625 | | m6 := mload(0xc0) 8626 | | // Selector of `log(uint256,address,string,bool)`. 8627 | | mstore(0x00, 0xcc32ab07) 8628 | | mstore(0x20, p0) 8629 | | mstore(0x40, p1) 8630 | | mstore(0x60, 0x80) 8631 | | mstore(0x80, p3) 8632 | | writeString(0xa0, p2) 8633 | | } 8634 | | _sendLogPayload(0x1c, 0xc4); 8635 | | /// @solidity memory-safe-assembly 8636 | | assembly { 8637 | | mstore(0x00, m0) 8638 | | mstore(0x20, m1) 8639 | | mstore(0x40, m2) 8640 | | mstore(0x60, m3) 8641 | | mstore(0x80, m4) 8642 | | mstore(0xa0, m5) 8643 | | mstore(0xc0, m6) 8644 | | } 8645 | | } 8646 | | 8647 | | function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure { 8648 | | bytes32 m0; 8649 | | bytes32 m1; 8650 | | bytes32 m2; 8651 | | bytes32 m3; 8652 | | bytes32 m4; 8653 | | bytes32 m5; 8654 | | bytes32 m6; 8655 | | /// @solidity memory-safe-assembly 8656 | | assembly { 8657 | | function writeString(pos, w) { 8658 | | let length := 0 8659 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8660 | | mstore(pos, length) 8661 | | let shift := sub(256, shl(3, length)) 8662 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8663 | | } 8664 | | m0 := mload(0x00) 8665 | | m1 := mload(0x20) 8666 | | m2 := mload(0x40) 8667 | | m3 := mload(0x60) 8668 | | m4 := mload(0x80) 8669 | | m5 := mload(0xa0) 8670 | | m6 := mload(0xc0) 8671 | | // Selector of `log(uint256,address,string,uint256)`. 8672 | | mstore(0x00, 0x46826b5d) 8673 | | mstore(0x20, p0) 8674 | | mstore(0x40, p1) 8675 | | mstore(0x60, 0x80) 8676 | | mstore(0x80, p3) 8677 | | writeString(0xa0, p2) 8678 | | } 8679 | | _sendLogPayload(0x1c, 0xc4); 8680 | | /// @solidity memory-safe-assembly 8681 | | assembly { 8682 | | mstore(0x00, m0) 8683 | | mstore(0x20, m1) 8684 | | mstore(0x40, m2) 8685 | | mstore(0x60, m3) 8686 | | mstore(0x80, m4) 8687 | | mstore(0xa0, m5) 8688 | | mstore(0xc0, m6) 8689 | | } 8690 | | } 8691 | | 8692 | | function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure { 8693 | | bytes32 m0; 8694 | | bytes32 m1; 8695 | | bytes32 m2; 8696 | | bytes32 m3; 8697 | | bytes32 m4; 8698 | | bytes32 m5; 8699 | | bytes32 m6; 8700 | | bytes32 m7; 8701 | | bytes32 m8; 8702 | | /// @solidity memory-safe-assembly 8703 | | assembly { 8704 | | function writeString(pos, w) { 8705 | | let length := 0 8706 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8707 | | mstore(pos, length) 8708 | | let shift := sub(256, shl(3, length)) 8709 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8710 | | } 8711 | | m0 := mload(0x00) 8712 | | m1 := mload(0x20) 8713 | | m2 := mload(0x40) 8714 | | m3 := mload(0x60) 8715 | | m4 := mload(0x80) 8716 | | m5 := mload(0xa0) 8717 | | m6 := mload(0xc0) 8718 | | m7 := mload(0xe0) 8719 | | m8 := mload(0x100) 8720 | | // Selector of `log(uint256,address,string,string)`. 8721 | | mstore(0x00, 0x3e128ca3) 8722 | | mstore(0x20, p0) 8723 | | mstore(0x40, p1) 8724 | | mstore(0x60, 0x80) 8725 | | mstore(0x80, 0xc0) 8726 | | writeString(0xa0, p2) 8727 | | writeString(0xe0, p3) 8728 | | } 8729 | | _sendLogPayload(0x1c, 0x104); 8730 | | /// @solidity memory-safe-assembly 8731 | | assembly { 8732 | | mstore(0x00, m0) 8733 | | mstore(0x20, m1) 8734 | | mstore(0x40, m2) 8735 | | mstore(0x60, m3) 8736 | | mstore(0x80, m4) 8737 | | mstore(0xa0, m5) 8738 | | mstore(0xc0, m6) 8739 | | mstore(0xe0, m7) 8740 | | mstore(0x100, m8) 8741 | | } 8742 | | } 8743 | | 8744 | | function log(uint256 p0, bool p1, address p2, address p3) internal pure { 8745 | | bytes32 m0; 8746 | | bytes32 m1; 8747 | | bytes32 m2; 8748 | | bytes32 m3; 8749 | | bytes32 m4; 8750 | | /// @solidity memory-safe-assembly 8751 | | assembly { 8752 | | m0 := mload(0x00) 8753 | | m1 := mload(0x20) 8754 | | m2 := mload(0x40) 8755 | | m3 := mload(0x60) 8756 | | m4 := mload(0x80) 8757 | | // Selector of `log(uint256,bool,address,address)`. 8758 | | mstore(0x00, 0xa1ef4cbb) 8759 | | mstore(0x20, p0) 8760 | | mstore(0x40, p1) 8761 | | mstore(0x60, p2) 8762 | | mstore(0x80, p3) 8763 | | } 8764 | | _sendLogPayload(0x1c, 0x84); 8765 | | /// @solidity memory-safe-assembly 8766 | | assembly { 8767 | | mstore(0x00, m0) 8768 | | mstore(0x20, m1) 8769 | | mstore(0x40, m2) 8770 | | mstore(0x60, m3) 8771 | | mstore(0x80, m4) 8772 | | } 8773 | | } 8774 | | 8775 | | function log(uint256 p0, bool p1, address p2, bool p3) internal pure { 8776 | | bytes32 m0; 8777 | | bytes32 m1; 8778 | | bytes32 m2; 8779 | | bytes32 m3; 8780 | | bytes32 m4; 8781 | | /// @solidity memory-safe-assembly 8782 | | assembly { 8783 | | m0 := mload(0x00) 8784 | | m1 := mload(0x20) 8785 | | m2 := mload(0x40) 8786 | | m3 := mload(0x60) 8787 | | m4 := mload(0x80) 8788 | | // Selector of `log(uint256,bool,address,bool)`. 8789 | | mstore(0x00, 0x454d54a5) 8790 | | mstore(0x20, p0) 8791 | | mstore(0x40, p1) 8792 | | mstore(0x60, p2) 8793 | | mstore(0x80, p3) 8794 | | } 8795 | | _sendLogPayload(0x1c, 0x84); 8796 | | /// @solidity memory-safe-assembly 8797 | | assembly { 8798 | | mstore(0x00, m0) 8799 | | mstore(0x20, m1) 8800 | | mstore(0x40, m2) 8801 | | mstore(0x60, m3) 8802 | | mstore(0x80, m4) 8803 | | } 8804 | | } 8805 | | 8806 | | function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { 8807 | | bytes32 m0; 8808 | | bytes32 m1; 8809 | | bytes32 m2; 8810 | | bytes32 m3; 8811 | | bytes32 m4; 8812 | | /// @solidity memory-safe-assembly 8813 | | assembly { 8814 | | m0 := mload(0x00) 8815 | | m1 := mload(0x20) 8816 | | m2 := mload(0x40) 8817 | | m3 := mload(0x60) 8818 | | m4 := mload(0x80) 8819 | | // Selector of `log(uint256,bool,address,uint256)`. 8820 | | mstore(0x00, 0x078287f5) 8821 | | mstore(0x20, p0) 8822 | | mstore(0x40, p1) 8823 | | mstore(0x60, p2) 8824 | | mstore(0x80, p3) 8825 | | } 8826 | | _sendLogPayload(0x1c, 0x84); 8827 | | /// @solidity memory-safe-assembly 8828 | | assembly { 8829 | | mstore(0x00, m0) 8830 | | mstore(0x20, m1) 8831 | | mstore(0x40, m2) 8832 | | mstore(0x60, m3) 8833 | | mstore(0x80, m4) 8834 | | } 8835 | | } 8836 | | 8837 | | function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure { 8838 | | bytes32 m0; 8839 | | bytes32 m1; 8840 | | bytes32 m2; 8841 | | bytes32 m3; 8842 | | bytes32 m4; 8843 | | bytes32 m5; 8844 | | bytes32 m6; 8845 | | /// @solidity memory-safe-assembly 8846 | | assembly { 8847 | | function writeString(pos, w) { 8848 | | let length := 0 8849 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8850 | | mstore(pos, length) 8851 | | let shift := sub(256, shl(3, length)) 8852 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8853 | | } 8854 | | m0 := mload(0x00) 8855 | | m1 := mload(0x20) 8856 | | m2 := mload(0x40) 8857 | | m3 := mload(0x60) 8858 | | m4 := mload(0x80) 8859 | | m5 := mload(0xa0) 8860 | | m6 := mload(0xc0) 8861 | | // Selector of `log(uint256,bool,address,string)`. 8862 | | mstore(0x00, 0xade052c7) 8863 | | mstore(0x20, p0) 8864 | | mstore(0x40, p1) 8865 | | mstore(0x60, p2) 8866 | | mstore(0x80, 0x80) 8867 | | writeString(0xa0, p3) 8868 | | } 8869 | | _sendLogPayload(0x1c, 0xc4); 8870 | | /// @solidity memory-safe-assembly 8871 | | assembly { 8872 | | mstore(0x00, m0) 8873 | | mstore(0x20, m1) 8874 | | mstore(0x40, m2) 8875 | | mstore(0x60, m3) 8876 | | mstore(0x80, m4) 8877 | | mstore(0xa0, m5) 8878 | | mstore(0xc0, m6) 8879 | | } 8880 | | } 8881 | | 8882 | | function log(uint256 p0, bool p1, bool p2, address p3) internal pure { 8883 | | bytes32 m0; 8884 | | bytes32 m1; 8885 | | bytes32 m2; 8886 | | bytes32 m3; 8887 | | bytes32 m4; 8888 | | /// @solidity memory-safe-assembly 8889 | | assembly { 8890 | | m0 := mload(0x00) 8891 | | m1 := mload(0x20) 8892 | | m2 := mload(0x40) 8893 | | m3 := mload(0x60) 8894 | | m4 := mload(0x80) 8895 | | // Selector of `log(uint256,bool,bool,address)`. 8896 | | mstore(0x00, 0x69640b59) 8897 | | mstore(0x20, p0) 8898 | | mstore(0x40, p1) 8899 | | mstore(0x60, p2) 8900 | | mstore(0x80, p3) 8901 | | } 8902 | | _sendLogPayload(0x1c, 0x84); 8903 | | /// @solidity memory-safe-assembly 8904 | | assembly { 8905 | | mstore(0x00, m0) 8906 | | mstore(0x20, m1) 8907 | | mstore(0x40, m2) 8908 | | mstore(0x60, m3) 8909 | | mstore(0x80, m4) 8910 | | } 8911 | | } 8912 | | 8913 | | function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { 8914 | | bytes32 m0; 8915 | | bytes32 m1; 8916 | | bytes32 m2; 8917 | | bytes32 m3; 8918 | | bytes32 m4; 8919 | | /// @solidity memory-safe-assembly 8920 | | assembly { 8921 | | m0 := mload(0x00) 8922 | | m1 := mload(0x20) 8923 | | m2 := mload(0x40) 8924 | | m3 := mload(0x60) 8925 | | m4 := mload(0x80) 8926 | | // Selector of `log(uint256,bool,bool,bool)`. 8927 | | mstore(0x00, 0xb6f577a1) 8928 | | mstore(0x20, p0) 8929 | | mstore(0x40, p1) 8930 | | mstore(0x60, p2) 8931 | | mstore(0x80, p3) 8932 | | } 8933 | | _sendLogPayload(0x1c, 0x84); 8934 | | /// @solidity memory-safe-assembly 8935 | | assembly { 8936 | | mstore(0x00, m0) 8937 | | mstore(0x20, m1) 8938 | | mstore(0x40, m2) 8939 | | mstore(0x60, m3) 8940 | | mstore(0x80, m4) 8941 | | } 8942 | | } 8943 | | 8944 | | function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { 8945 | | bytes32 m0; 8946 | | bytes32 m1; 8947 | | bytes32 m2; 8948 | | bytes32 m3; 8949 | | bytes32 m4; 8950 | | /// @solidity memory-safe-assembly 8951 | | assembly { 8952 | | m0 := mload(0x00) 8953 | | m1 := mload(0x20) 8954 | | m2 := mload(0x40) 8955 | | m3 := mload(0x60) 8956 | | m4 := mload(0x80) 8957 | | // Selector of `log(uint256,bool,bool,uint256)`. 8958 | | mstore(0x00, 0x7464ce23) 8959 | | mstore(0x20, p0) 8960 | | mstore(0x40, p1) 8961 | | mstore(0x60, p2) 8962 | | mstore(0x80, p3) 8963 | | } 8964 | | _sendLogPayload(0x1c, 0x84); 8965 | | /// @solidity memory-safe-assembly 8966 | | assembly { 8967 | | mstore(0x00, m0) 8968 | | mstore(0x20, m1) 8969 | | mstore(0x40, m2) 8970 | | mstore(0x60, m3) 8971 | | mstore(0x80, m4) 8972 | | } 8973 | | } 8974 | | 8975 | | function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure { 8976 | | bytes32 m0; 8977 | | bytes32 m1; 8978 | | bytes32 m2; 8979 | | bytes32 m3; 8980 | | bytes32 m4; 8981 | | bytes32 m5; 8982 | | bytes32 m6; 8983 | | /// @solidity memory-safe-assembly 8984 | | assembly { 8985 | | function writeString(pos, w) { 8986 | | let length := 0 8987 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 8988 | | mstore(pos, length) 8989 | | let shift := sub(256, shl(3, length)) 8990 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 8991 | | } 8992 | | m0 := mload(0x00) 8993 | | m1 := mload(0x20) 8994 | | m2 := mload(0x40) 8995 | | m3 := mload(0x60) 8996 | | m4 := mload(0x80) 8997 | | m5 := mload(0xa0) 8998 | | m6 := mload(0xc0) 8999 | | // Selector of `log(uint256,bool,bool,string)`. 9000 | | mstore(0x00, 0xdddb9561) 9001 | | mstore(0x20, p0) 9002 | | mstore(0x40, p1) 9003 | | mstore(0x60, p2) 9004 | | mstore(0x80, 0x80) 9005 | | writeString(0xa0, p3) 9006 | | } 9007 | | _sendLogPayload(0x1c, 0xc4); 9008 | | /// @solidity memory-safe-assembly 9009 | | assembly { 9010 | | mstore(0x00, m0) 9011 | | mstore(0x20, m1) 9012 | | mstore(0x40, m2) 9013 | | mstore(0x60, m3) 9014 | | mstore(0x80, m4) 9015 | | mstore(0xa0, m5) 9016 | | mstore(0xc0, m6) 9017 | | } 9018 | | } 9019 | | 9020 | | function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { 9021 | | bytes32 m0; 9022 | | bytes32 m1; 9023 | | bytes32 m2; 9024 | | bytes32 m3; 9025 | | bytes32 m4; 9026 | | /// @solidity memory-safe-assembly 9027 | | assembly { 9028 | | m0 := mload(0x00) 9029 | | m1 := mload(0x20) 9030 | | m2 := mload(0x40) 9031 | | m3 := mload(0x60) 9032 | | m4 := mload(0x80) 9033 | | // Selector of `log(uint256,bool,uint256,address)`. 9034 | | mstore(0x00, 0x88cb6041) 9035 | | mstore(0x20, p0) 9036 | | mstore(0x40, p1) 9037 | | mstore(0x60, p2) 9038 | | mstore(0x80, p3) 9039 | | } 9040 | | _sendLogPayload(0x1c, 0x84); 9041 | | /// @solidity memory-safe-assembly 9042 | | assembly { 9043 | | mstore(0x00, m0) 9044 | | mstore(0x20, m1) 9045 | | mstore(0x40, m2) 9046 | | mstore(0x60, m3) 9047 | | mstore(0x80, m4) 9048 | | } 9049 | | } 9050 | | 9051 | | function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { 9052 | | bytes32 m0; 9053 | | bytes32 m1; 9054 | | bytes32 m2; 9055 | | bytes32 m3; 9056 | | bytes32 m4; 9057 | | /// @solidity memory-safe-assembly 9058 | | assembly { 9059 | | m0 := mload(0x00) 9060 | | m1 := mload(0x20) 9061 | | m2 := mload(0x40) 9062 | | m3 := mload(0x60) 9063 | | m4 := mload(0x80) 9064 | | // Selector of `log(uint256,bool,uint256,bool)`. 9065 | | mstore(0x00, 0x91a02e2a) 9066 | | mstore(0x20, p0) 9067 | | mstore(0x40, p1) 9068 | | mstore(0x60, p2) 9069 | | mstore(0x80, p3) 9070 | | } 9071 | | _sendLogPayload(0x1c, 0x84); 9072 | | /// @solidity memory-safe-assembly 9073 | | assembly { 9074 | | mstore(0x00, m0) 9075 | | mstore(0x20, m1) 9076 | | mstore(0x40, m2) 9077 | | mstore(0x60, m3) 9078 | | mstore(0x80, m4) 9079 | | } 9080 | | } 9081 | | 9082 | | function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { 9083 | | bytes32 m0; 9084 | | bytes32 m1; 9085 | | bytes32 m2; 9086 | | bytes32 m3; 9087 | | bytes32 m4; 9088 | | /// @solidity memory-safe-assembly 9089 | | assembly { 9090 | | m0 := mload(0x00) 9091 | | m1 := mload(0x20) 9092 | | m2 := mload(0x40) 9093 | | m3 := mload(0x60) 9094 | | m4 := mload(0x80) 9095 | | // Selector of `log(uint256,bool,uint256,uint256)`. 9096 | | mstore(0x00, 0xc6acc7a8) 9097 | | mstore(0x20, p0) 9098 | | mstore(0x40, p1) 9099 | | mstore(0x60, p2) 9100 | | mstore(0x80, p3) 9101 | | } 9102 | | _sendLogPayload(0x1c, 0x84); 9103 | | /// @solidity memory-safe-assembly 9104 | | assembly { 9105 | | mstore(0x00, m0) 9106 | | mstore(0x20, m1) 9107 | | mstore(0x40, m2) 9108 | | mstore(0x60, m3) 9109 | | mstore(0x80, m4) 9110 | | } 9111 | | } 9112 | | 9113 | | function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure { 9114 | | bytes32 m0; 9115 | | bytes32 m1; 9116 | | bytes32 m2; 9117 | | bytes32 m3; 9118 | | bytes32 m4; 9119 | | bytes32 m5; 9120 | | bytes32 m6; 9121 | | /// @solidity memory-safe-assembly 9122 | | assembly { 9123 | | function writeString(pos, w) { 9124 | | let length := 0 9125 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9126 | | mstore(pos, length) 9127 | | let shift := sub(256, shl(3, length)) 9128 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9129 | | } 9130 | | m0 := mload(0x00) 9131 | | m1 := mload(0x20) 9132 | | m2 := mload(0x40) 9133 | | m3 := mload(0x60) 9134 | | m4 := mload(0x80) 9135 | | m5 := mload(0xa0) 9136 | | m6 := mload(0xc0) 9137 | | // Selector of `log(uint256,bool,uint256,string)`. 9138 | | mstore(0x00, 0xde03e774) 9139 | | mstore(0x20, p0) 9140 | | mstore(0x40, p1) 9141 | | mstore(0x60, p2) 9142 | | mstore(0x80, 0x80) 9143 | | writeString(0xa0, p3) 9144 | | } 9145 | | _sendLogPayload(0x1c, 0xc4); 9146 | | /// @solidity memory-safe-assembly 9147 | | assembly { 9148 | | mstore(0x00, m0) 9149 | | mstore(0x20, m1) 9150 | | mstore(0x40, m2) 9151 | | mstore(0x60, m3) 9152 | | mstore(0x80, m4) 9153 | | mstore(0xa0, m5) 9154 | | mstore(0xc0, m6) 9155 | | } 9156 | | } 9157 | | 9158 | | function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure { 9159 | | bytes32 m0; 9160 | | bytes32 m1; 9161 | | bytes32 m2; 9162 | | bytes32 m3; 9163 | | bytes32 m4; 9164 | | bytes32 m5; 9165 | | bytes32 m6; 9166 | | /// @solidity memory-safe-assembly 9167 | | assembly { 9168 | | function writeString(pos, w) { 9169 | | let length := 0 9170 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9171 | | mstore(pos, length) 9172 | | let shift := sub(256, shl(3, length)) 9173 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9174 | | } 9175 | | m0 := mload(0x00) 9176 | | m1 := mload(0x20) 9177 | | m2 := mload(0x40) 9178 | | m3 := mload(0x60) 9179 | | m4 := mload(0x80) 9180 | | m5 := mload(0xa0) 9181 | | m6 := mload(0xc0) 9182 | | // Selector of `log(uint256,bool,string,address)`. 9183 | | mstore(0x00, 0xef529018) 9184 | | mstore(0x20, p0) 9185 | | mstore(0x40, p1) 9186 | | mstore(0x60, 0x80) 9187 | | mstore(0x80, p3) 9188 | | writeString(0xa0, p2) 9189 | | } 9190 | | _sendLogPayload(0x1c, 0xc4); 9191 | | /// @solidity memory-safe-assembly 9192 | | assembly { 9193 | | mstore(0x00, m0) 9194 | | mstore(0x20, m1) 9195 | | mstore(0x40, m2) 9196 | | mstore(0x60, m3) 9197 | | mstore(0x80, m4) 9198 | | mstore(0xa0, m5) 9199 | | mstore(0xc0, m6) 9200 | | } 9201 | | } 9202 | | 9203 | | function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure { 9204 | | bytes32 m0; 9205 | | bytes32 m1; 9206 | | bytes32 m2; 9207 | | bytes32 m3; 9208 | | bytes32 m4; 9209 | | bytes32 m5; 9210 | | bytes32 m6; 9211 | | /// @solidity memory-safe-assembly 9212 | | assembly { 9213 | | function writeString(pos, w) { 9214 | | let length := 0 9215 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9216 | | mstore(pos, length) 9217 | | let shift := sub(256, shl(3, length)) 9218 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9219 | | } 9220 | | m0 := mload(0x00) 9221 | | m1 := mload(0x20) 9222 | | m2 := mload(0x40) 9223 | | m3 := mload(0x60) 9224 | | m4 := mload(0x80) 9225 | | m5 := mload(0xa0) 9226 | | m6 := mload(0xc0) 9227 | | // Selector of `log(uint256,bool,string,bool)`. 9228 | | mstore(0x00, 0xeb928d7f) 9229 | | mstore(0x20, p0) 9230 | | mstore(0x40, p1) 9231 | | mstore(0x60, 0x80) 9232 | | mstore(0x80, p3) 9233 | | writeString(0xa0, p2) 9234 | | } 9235 | | _sendLogPayload(0x1c, 0xc4); 9236 | | /// @solidity memory-safe-assembly 9237 | | assembly { 9238 | | mstore(0x00, m0) 9239 | | mstore(0x20, m1) 9240 | | mstore(0x40, m2) 9241 | | mstore(0x60, m3) 9242 | | mstore(0x80, m4) 9243 | | mstore(0xa0, m5) 9244 | | mstore(0xc0, m6) 9245 | | } 9246 | | } 9247 | | 9248 | | function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure { 9249 | | bytes32 m0; 9250 | | bytes32 m1; 9251 | | bytes32 m2; 9252 | | bytes32 m3; 9253 | | bytes32 m4; 9254 | | bytes32 m5; 9255 | | bytes32 m6; 9256 | | /// @solidity memory-safe-assembly 9257 | | assembly { 9258 | | function writeString(pos, w) { 9259 | | let length := 0 9260 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9261 | | mstore(pos, length) 9262 | | let shift := sub(256, shl(3, length)) 9263 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9264 | | } 9265 | | m0 := mload(0x00) 9266 | | m1 := mload(0x20) 9267 | | m2 := mload(0x40) 9268 | | m3 := mload(0x60) 9269 | | m4 := mload(0x80) 9270 | | m5 := mload(0xa0) 9271 | | m6 := mload(0xc0) 9272 | | // Selector of `log(uint256,bool,string,uint256)`. 9273 | | mstore(0x00, 0x2c1d0746) 9274 | | mstore(0x20, p0) 9275 | | mstore(0x40, p1) 9276 | | mstore(0x60, 0x80) 9277 | | mstore(0x80, p3) 9278 | | writeString(0xa0, p2) 9279 | | } 9280 | | _sendLogPayload(0x1c, 0xc4); 9281 | | /// @solidity memory-safe-assembly 9282 | | assembly { 9283 | | mstore(0x00, m0) 9284 | | mstore(0x20, m1) 9285 | | mstore(0x40, m2) 9286 | | mstore(0x60, m3) 9287 | | mstore(0x80, m4) 9288 | | mstore(0xa0, m5) 9289 | | mstore(0xc0, m6) 9290 | | } 9291 | | } 9292 | | 9293 | | function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { 9294 | | bytes32 m0; 9295 | | bytes32 m1; 9296 | | bytes32 m2; 9297 | | bytes32 m3; 9298 | | bytes32 m4; 9299 | | bytes32 m5; 9300 | | bytes32 m6; 9301 | | bytes32 m7; 9302 | | bytes32 m8; 9303 | | /// @solidity memory-safe-assembly 9304 | | assembly { 9305 | | function writeString(pos, w) { 9306 | | let length := 0 9307 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9308 | | mstore(pos, length) 9309 | | let shift := sub(256, shl(3, length)) 9310 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9311 | | } 9312 | | m0 := mload(0x00) 9313 | | m1 := mload(0x20) 9314 | | m2 := mload(0x40) 9315 | | m3 := mload(0x60) 9316 | | m4 := mload(0x80) 9317 | | m5 := mload(0xa0) 9318 | | m6 := mload(0xc0) 9319 | | m7 := mload(0xe0) 9320 | | m8 := mload(0x100) 9321 | | // Selector of `log(uint256,bool,string,string)`. 9322 | | mstore(0x00, 0x68c8b8bd) 9323 | | mstore(0x20, p0) 9324 | | mstore(0x40, p1) 9325 | | mstore(0x60, 0x80) 9326 | | mstore(0x80, 0xc0) 9327 | | writeString(0xa0, p2) 9328 | | writeString(0xe0, p3) 9329 | | } 9330 | | _sendLogPayload(0x1c, 0x104); 9331 | | /// @solidity memory-safe-assembly 9332 | | assembly { 9333 | | mstore(0x00, m0) 9334 | | mstore(0x20, m1) 9335 | | mstore(0x40, m2) 9336 | | mstore(0x60, m3) 9337 | | mstore(0x80, m4) 9338 | | mstore(0xa0, m5) 9339 | | mstore(0xc0, m6) 9340 | | mstore(0xe0, m7) 9341 | | mstore(0x100, m8) 9342 | | } 9343 | | } 9344 | | 9345 | | function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { 9346 | | bytes32 m0; 9347 | | bytes32 m1; 9348 | | bytes32 m2; 9349 | | bytes32 m3; 9350 | | bytes32 m4; 9351 | | /// @solidity memory-safe-assembly 9352 | | assembly { 9353 | | m0 := mload(0x00) 9354 | | m1 := mload(0x20) 9355 | | m2 := mload(0x40) 9356 | | m3 := mload(0x60) 9357 | | m4 := mload(0x80) 9358 | | // Selector of `log(uint256,uint256,address,address)`. 9359 | | mstore(0x00, 0x56a5d1b1) 9360 | | mstore(0x20, p0) 9361 | | mstore(0x40, p1) 9362 | | mstore(0x60, p2) 9363 | | mstore(0x80, p3) 9364 | | } 9365 | | _sendLogPayload(0x1c, 0x84); 9366 | | /// @solidity memory-safe-assembly 9367 | | assembly { 9368 | | mstore(0x00, m0) 9369 | | mstore(0x20, m1) 9370 | | mstore(0x40, m2) 9371 | | mstore(0x60, m3) 9372 | | mstore(0x80, m4) 9373 | | } 9374 | | } 9375 | | 9376 | | function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { 9377 | | bytes32 m0; 9378 | | bytes32 m1; 9379 | | bytes32 m2; 9380 | | bytes32 m3; 9381 | | bytes32 m4; 9382 | | /// @solidity memory-safe-assembly 9383 | | assembly { 9384 | | m0 := mload(0x00) 9385 | | m1 := mload(0x20) 9386 | | m2 := mload(0x40) 9387 | | m3 := mload(0x60) 9388 | | m4 := mload(0x80) 9389 | | // Selector of `log(uint256,uint256,address,bool)`. 9390 | | mstore(0x00, 0x15cac476) 9391 | | mstore(0x20, p0) 9392 | | mstore(0x40, p1) 9393 | | mstore(0x60, p2) 9394 | | mstore(0x80, p3) 9395 | | } 9396 | | _sendLogPayload(0x1c, 0x84); 9397 | | /// @solidity memory-safe-assembly 9398 | | assembly { 9399 | | mstore(0x00, m0) 9400 | | mstore(0x20, m1) 9401 | | mstore(0x40, m2) 9402 | | mstore(0x60, m3) 9403 | | mstore(0x80, m4) 9404 | | } 9405 | | } 9406 | | 9407 | | function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { 9408 | | bytes32 m0; 9409 | | bytes32 m1; 9410 | | bytes32 m2; 9411 | | bytes32 m3; 9412 | | bytes32 m4; 9413 | | /// @solidity memory-safe-assembly 9414 | | assembly { 9415 | | m0 := mload(0x00) 9416 | | m1 := mload(0x20) 9417 | | m2 := mload(0x40) 9418 | | m3 := mload(0x60) 9419 | | m4 := mload(0x80) 9420 | | // Selector of `log(uint256,uint256,address,uint256)`. 9421 | | mstore(0x00, 0x88f6e4b2) 9422 | | mstore(0x20, p0) 9423 | | mstore(0x40, p1) 9424 | | mstore(0x60, p2) 9425 | | mstore(0x80, p3) 9426 | | } 9427 | | _sendLogPayload(0x1c, 0x84); 9428 | | /// @solidity memory-safe-assembly 9429 | | assembly { 9430 | | mstore(0x00, m0) 9431 | | mstore(0x20, m1) 9432 | | mstore(0x40, m2) 9433 | | mstore(0x60, m3) 9434 | | mstore(0x80, m4) 9435 | | } 9436 | | } 9437 | | 9438 | | function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure { 9439 | | bytes32 m0; 9440 | | bytes32 m1; 9441 | | bytes32 m2; 9442 | | bytes32 m3; 9443 | | bytes32 m4; 9444 | | bytes32 m5; 9445 | | bytes32 m6; 9446 | | /// @solidity memory-safe-assembly 9447 | | assembly { 9448 | | function writeString(pos, w) { 9449 | | let length := 0 9450 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9451 | | mstore(pos, length) 9452 | | let shift := sub(256, shl(3, length)) 9453 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9454 | | } 9455 | | m0 := mload(0x00) 9456 | | m1 := mload(0x20) 9457 | | m2 := mload(0x40) 9458 | | m3 := mload(0x60) 9459 | | m4 := mload(0x80) 9460 | | m5 := mload(0xa0) 9461 | | m6 := mload(0xc0) 9462 | | // Selector of `log(uint256,uint256,address,string)`. 9463 | | mstore(0x00, 0x6cde40b8) 9464 | | mstore(0x20, p0) 9465 | | mstore(0x40, p1) 9466 | | mstore(0x60, p2) 9467 | | mstore(0x80, 0x80) 9468 | | writeString(0xa0, p3) 9469 | | } 9470 | | _sendLogPayload(0x1c, 0xc4); 9471 | | /// @solidity memory-safe-assembly 9472 | | assembly { 9473 | | mstore(0x00, m0) 9474 | | mstore(0x20, m1) 9475 | | mstore(0x40, m2) 9476 | | mstore(0x60, m3) 9477 | | mstore(0x80, m4) 9478 | | mstore(0xa0, m5) 9479 | | mstore(0xc0, m6) 9480 | | } 9481 | | } 9482 | | 9483 | | function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { 9484 | | bytes32 m0; 9485 | | bytes32 m1; 9486 | | bytes32 m2; 9487 | | bytes32 m3; 9488 | | bytes32 m4; 9489 | | /// @solidity memory-safe-assembly 9490 | | assembly { 9491 | | m0 := mload(0x00) 9492 | | m1 := mload(0x20) 9493 | | m2 := mload(0x40) 9494 | | m3 := mload(0x60) 9495 | | m4 := mload(0x80) 9496 | | // Selector of `log(uint256,uint256,bool,address)`. 9497 | | mstore(0x00, 0x9a816a83) 9498 | | mstore(0x20, p0) 9499 | | mstore(0x40, p1) 9500 | | mstore(0x60, p2) 9501 | | mstore(0x80, p3) 9502 | | } 9503 | | _sendLogPayload(0x1c, 0x84); 9504 | | /// @solidity memory-safe-assembly 9505 | | assembly { 9506 | | mstore(0x00, m0) 9507 | | mstore(0x20, m1) 9508 | | mstore(0x40, m2) 9509 | | mstore(0x60, m3) 9510 | | mstore(0x80, m4) 9511 | | } 9512 | | } 9513 | | 9514 | | function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { 9515 | | bytes32 m0; 9516 | | bytes32 m1; 9517 | | bytes32 m2; 9518 | | bytes32 m3; 9519 | | bytes32 m4; 9520 | | /// @solidity memory-safe-assembly 9521 | | assembly { 9522 | | m0 := mload(0x00) 9523 | | m1 := mload(0x20) 9524 | | m2 := mload(0x40) 9525 | | m3 := mload(0x60) 9526 | | m4 := mload(0x80) 9527 | | // Selector of `log(uint256,uint256,bool,bool)`. 9528 | | mstore(0x00, 0xab085ae6) 9529 | | mstore(0x20, p0) 9530 | | mstore(0x40, p1) 9531 | | mstore(0x60, p2) 9532 | | mstore(0x80, p3) 9533 | | } 9534 | | _sendLogPayload(0x1c, 0x84); 9535 | | /// @solidity memory-safe-assembly 9536 | | assembly { 9537 | | mstore(0x00, m0) 9538 | | mstore(0x20, m1) 9539 | | mstore(0x40, m2) 9540 | | mstore(0x60, m3) 9541 | | mstore(0x80, m4) 9542 | | } 9543 | | } 9544 | | 9545 | | function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { 9546 | | bytes32 m0; 9547 | | bytes32 m1; 9548 | | bytes32 m2; 9549 | | bytes32 m3; 9550 | | bytes32 m4; 9551 | | /// @solidity memory-safe-assembly 9552 | | assembly { 9553 | | m0 := mload(0x00) 9554 | | m1 := mload(0x20) 9555 | | m2 := mload(0x40) 9556 | | m3 := mload(0x60) 9557 | | m4 := mload(0x80) 9558 | | // Selector of `log(uint256,uint256,bool,uint256)`. 9559 | | mstore(0x00, 0xeb7f6fd2) 9560 | | mstore(0x20, p0) 9561 | | mstore(0x40, p1) 9562 | | mstore(0x60, p2) 9563 | | mstore(0x80, p3) 9564 | | } 9565 | | _sendLogPayload(0x1c, 0x84); 9566 | | /// @solidity memory-safe-assembly 9567 | | assembly { 9568 | | mstore(0x00, m0) 9569 | | mstore(0x20, m1) 9570 | | mstore(0x40, m2) 9571 | | mstore(0x60, m3) 9572 | | mstore(0x80, m4) 9573 | | } 9574 | | } 9575 | | 9576 | | function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure { 9577 | | bytes32 m0; 9578 | | bytes32 m1; 9579 | | bytes32 m2; 9580 | | bytes32 m3; 9581 | | bytes32 m4; 9582 | | bytes32 m5; 9583 | | bytes32 m6; 9584 | | /// @solidity memory-safe-assembly 9585 | | assembly { 9586 | | function writeString(pos, w) { 9587 | | let length := 0 9588 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9589 | | mstore(pos, length) 9590 | | let shift := sub(256, shl(3, length)) 9591 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9592 | | } 9593 | | m0 := mload(0x00) 9594 | | m1 := mload(0x20) 9595 | | m2 := mload(0x40) 9596 | | m3 := mload(0x60) 9597 | | m4 := mload(0x80) 9598 | | m5 := mload(0xa0) 9599 | | m6 := mload(0xc0) 9600 | | // Selector of `log(uint256,uint256,bool,string)`. 9601 | | mstore(0x00, 0xa5b4fc99) 9602 | | mstore(0x20, p0) 9603 | | mstore(0x40, p1) 9604 | | mstore(0x60, p2) 9605 | | mstore(0x80, 0x80) 9606 | | writeString(0xa0, p3) 9607 | | } 9608 | | _sendLogPayload(0x1c, 0xc4); 9609 | | /// @solidity memory-safe-assembly 9610 | | assembly { 9611 | | mstore(0x00, m0) 9612 | | mstore(0x20, m1) 9613 | | mstore(0x40, m2) 9614 | | mstore(0x60, m3) 9615 | | mstore(0x80, m4) 9616 | | mstore(0xa0, m5) 9617 | | mstore(0xc0, m6) 9618 | | } 9619 | | } 9620 | | 9621 | | function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { 9622 | | bytes32 m0; 9623 | | bytes32 m1; 9624 | | bytes32 m2; 9625 | | bytes32 m3; 9626 | | bytes32 m4; 9627 | | /// @solidity memory-safe-assembly 9628 | | assembly { 9629 | | m0 := mload(0x00) 9630 | | m1 := mload(0x20) 9631 | | m2 := mload(0x40) 9632 | | m3 := mload(0x60) 9633 | | m4 := mload(0x80) 9634 | | // Selector of `log(uint256,uint256,uint256,address)`. 9635 | | mstore(0x00, 0xfa8185af) 9636 | | mstore(0x20, p0) 9637 | | mstore(0x40, p1) 9638 | | mstore(0x60, p2) 9639 | | mstore(0x80, p3) 9640 | | } 9641 | | _sendLogPayload(0x1c, 0x84); 9642 | | /// @solidity memory-safe-assembly 9643 | | assembly { 9644 | | mstore(0x00, m0) 9645 | | mstore(0x20, m1) 9646 | | mstore(0x40, m2) 9647 | | mstore(0x60, m3) 9648 | | mstore(0x80, m4) 9649 | | } 9650 | | } 9651 | | 9652 | | function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { 9653 | | bytes32 m0; 9654 | | bytes32 m1; 9655 | | bytes32 m2; 9656 | | bytes32 m3; 9657 | | bytes32 m4; 9658 | | /// @solidity memory-safe-assembly 9659 | | assembly { 9660 | | m0 := mload(0x00) 9661 | | m1 := mload(0x20) 9662 | | m2 := mload(0x40) 9663 | | m3 := mload(0x60) 9664 | | m4 := mload(0x80) 9665 | | // Selector of `log(uint256,uint256,uint256,bool)`. 9666 | | mstore(0x00, 0xc598d185) 9667 | | mstore(0x20, p0) 9668 | | mstore(0x40, p1) 9669 | | mstore(0x60, p2) 9670 | | mstore(0x80, p3) 9671 | | } 9672 | | _sendLogPayload(0x1c, 0x84); 9673 | | /// @solidity memory-safe-assembly 9674 | | assembly { 9675 | | mstore(0x00, m0) 9676 | | mstore(0x20, m1) 9677 | | mstore(0x40, m2) 9678 | | mstore(0x60, m3) 9679 | | mstore(0x80, m4) 9680 | | } 9681 | | } 9682 | | 9683 | | function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 9684 | | bytes32 m0; 9685 | | bytes32 m1; 9686 | | bytes32 m2; 9687 | | bytes32 m3; 9688 | | bytes32 m4; 9689 | | /// @solidity memory-safe-assembly 9690 | | assembly { 9691 | | m0 := mload(0x00) 9692 | | m1 := mload(0x20) 9693 | | m2 := mload(0x40) 9694 | | m3 := mload(0x60) 9695 | | m4 := mload(0x80) 9696 | | // Selector of `log(uint256,uint256,uint256,uint256)`. 9697 | | mstore(0x00, 0x193fb800) 9698 | | mstore(0x20, p0) 9699 | | mstore(0x40, p1) 9700 | | mstore(0x60, p2) 9701 | | mstore(0x80, p3) 9702 | | } 9703 | | _sendLogPayload(0x1c, 0x84); 9704 | | /// @solidity memory-safe-assembly 9705 | | assembly { 9706 | | mstore(0x00, m0) 9707 | | mstore(0x20, m1) 9708 | | mstore(0x40, m2) 9709 | | mstore(0x60, m3) 9710 | | mstore(0x80, m4) 9711 | | } 9712 | | } 9713 | | 9714 | | function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { 9715 | | bytes32 m0; 9716 | | bytes32 m1; 9717 | | bytes32 m2; 9718 | | bytes32 m3; 9719 | | bytes32 m4; 9720 | | bytes32 m5; 9721 | | bytes32 m6; 9722 | | /// @solidity memory-safe-assembly 9723 | | assembly { 9724 | | function writeString(pos, w) { 9725 | | let length := 0 9726 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9727 | | mstore(pos, length) 9728 | | let shift := sub(256, shl(3, length)) 9729 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9730 | | } 9731 | | m0 := mload(0x00) 9732 | | m1 := mload(0x20) 9733 | | m2 := mload(0x40) 9734 | | m3 := mload(0x60) 9735 | | m4 := mload(0x80) 9736 | | m5 := mload(0xa0) 9737 | | m6 := mload(0xc0) 9738 | | // Selector of `log(uint256,uint256,uint256,string)`. 9739 | | mstore(0x00, 0x59cfcbe3) 9740 | | mstore(0x20, p0) 9741 | | mstore(0x40, p1) 9742 | | mstore(0x60, p2) 9743 | | mstore(0x80, 0x80) 9744 | | writeString(0xa0, p3) 9745 | | } 9746 | | _sendLogPayload(0x1c, 0xc4); 9747 | | /// @solidity memory-safe-assembly 9748 | | assembly { 9749 | | mstore(0x00, m0) 9750 | | mstore(0x20, m1) 9751 | | mstore(0x40, m2) 9752 | | mstore(0x60, m3) 9753 | | mstore(0x80, m4) 9754 | | mstore(0xa0, m5) 9755 | | mstore(0xc0, m6) 9756 | | } 9757 | | } 9758 | | 9759 | | function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure { 9760 | | bytes32 m0; 9761 | | bytes32 m1; 9762 | | bytes32 m2; 9763 | | bytes32 m3; 9764 | | bytes32 m4; 9765 | | bytes32 m5; 9766 | | bytes32 m6; 9767 | | /// @solidity memory-safe-assembly 9768 | | assembly { 9769 | | function writeString(pos, w) { 9770 | | let length := 0 9771 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9772 | | mstore(pos, length) 9773 | | let shift := sub(256, shl(3, length)) 9774 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9775 | | } 9776 | | m0 := mload(0x00) 9777 | | m1 := mload(0x20) 9778 | | m2 := mload(0x40) 9779 | | m3 := mload(0x60) 9780 | | m4 := mload(0x80) 9781 | | m5 := mload(0xa0) 9782 | | m6 := mload(0xc0) 9783 | | // Selector of `log(uint256,uint256,string,address)`. 9784 | | mstore(0x00, 0x42d21db7) 9785 | | mstore(0x20, p0) 9786 | | mstore(0x40, p1) 9787 | | mstore(0x60, 0x80) 9788 | | mstore(0x80, p3) 9789 | | writeString(0xa0, p2) 9790 | | } 9791 | | _sendLogPayload(0x1c, 0xc4); 9792 | | /// @solidity memory-safe-assembly 9793 | | assembly { 9794 | | mstore(0x00, m0) 9795 | | mstore(0x20, m1) 9796 | | mstore(0x40, m2) 9797 | | mstore(0x60, m3) 9798 | | mstore(0x80, m4) 9799 | | mstore(0xa0, m5) 9800 | | mstore(0xc0, m6) 9801 | | } 9802 | | } 9803 | | 9804 | | function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure { 9805 | | bytes32 m0; 9806 | | bytes32 m1; 9807 | | bytes32 m2; 9808 | | bytes32 m3; 9809 | | bytes32 m4; 9810 | | bytes32 m5; 9811 | | bytes32 m6; 9812 | | /// @solidity memory-safe-assembly 9813 | | assembly { 9814 | | function writeString(pos, w) { 9815 | | let length := 0 9816 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9817 | | mstore(pos, length) 9818 | | let shift := sub(256, shl(3, length)) 9819 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9820 | | } 9821 | | m0 := mload(0x00) 9822 | | m1 := mload(0x20) 9823 | | m2 := mload(0x40) 9824 | | m3 := mload(0x60) 9825 | | m4 := mload(0x80) 9826 | | m5 := mload(0xa0) 9827 | | m6 := mload(0xc0) 9828 | | // Selector of `log(uint256,uint256,string,bool)`. 9829 | | mstore(0x00, 0x7af6ab25) 9830 | | mstore(0x20, p0) 9831 | | mstore(0x40, p1) 9832 | | mstore(0x60, 0x80) 9833 | | mstore(0x80, p3) 9834 | | writeString(0xa0, p2) 9835 | | } 9836 | | _sendLogPayload(0x1c, 0xc4); 9837 | | /// @solidity memory-safe-assembly 9838 | | assembly { 9839 | | mstore(0x00, m0) 9840 | | mstore(0x20, m1) 9841 | | mstore(0x40, m2) 9842 | | mstore(0x60, m3) 9843 | | mstore(0x80, m4) 9844 | | mstore(0xa0, m5) 9845 | | mstore(0xc0, m6) 9846 | | } 9847 | | } 9848 | | 9849 | | function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { 9850 | | bytes32 m0; 9851 | | bytes32 m1; 9852 | | bytes32 m2; 9853 | | bytes32 m3; 9854 | | bytes32 m4; 9855 | | bytes32 m5; 9856 | | bytes32 m6; 9857 | | /// @solidity memory-safe-assembly 9858 | | assembly { 9859 | | function writeString(pos, w) { 9860 | | let length := 0 9861 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9862 | | mstore(pos, length) 9863 | | let shift := sub(256, shl(3, length)) 9864 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9865 | | } 9866 | | m0 := mload(0x00) 9867 | | m1 := mload(0x20) 9868 | | m2 := mload(0x40) 9869 | | m3 := mload(0x60) 9870 | | m4 := mload(0x80) 9871 | | m5 := mload(0xa0) 9872 | | m6 := mload(0xc0) 9873 | | // Selector of `log(uint256,uint256,string,uint256)`. 9874 | | mstore(0x00, 0x5da297eb) 9875 | | mstore(0x20, p0) 9876 | | mstore(0x40, p1) 9877 | | mstore(0x60, 0x80) 9878 | | mstore(0x80, p3) 9879 | | writeString(0xa0, p2) 9880 | | } 9881 | | _sendLogPayload(0x1c, 0xc4); 9882 | | /// @solidity memory-safe-assembly 9883 | | assembly { 9884 | | mstore(0x00, m0) 9885 | | mstore(0x20, m1) 9886 | | mstore(0x40, m2) 9887 | | mstore(0x60, m3) 9888 | | mstore(0x80, m4) 9889 | | mstore(0xa0, m5) 9890 | | mstore(0xc0, m6) 9891 | | } 9892 | | } 9893 | | 9894 | | function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { 9895 | | bytes32 m0; 9896 | | bytes32 m1; 9897 | | bytes32 m2; 9898 | | bytes32 m3; 9899 | | bytes32 m4; 9900 | | bytes32 m5; 9901 | | bytes32 m6; 9902 | | bytes32 m7; 9903 | | bytes32 m8; 9904 | | /// @solidity memory-safe-assembly 9905 | | assembly { 9906 | | function writeString(pos, w) { 9907 | | let length := 0 9908 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9909 | | mstore(pos, length) 9910 | | let shift := sub(256, shl(3, length)) 9911 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9912 | | } 9913 | | m0 := mload(0x00) 9914 | | m1 := mload(0x20) 9915 | | m2 := mload(0x40) 9916 | | m3 := mload(0x60) 9917 | | m4 := mload(0x80) 9918 | | m5 := mload(0xa0) 9919 | | m6 := mload(0xc0) 9920 | | m7 := mload(0xe0) 9921 | | m8 := mload(0x100) 9922 | | // Selector of `log(uint256,uint256,string,string)`. 9923 | | mstore(0x00, 0x27d8afd2) 9924 | | mstore(0x20, p0) 9925 | | mstore(0x40, p1) 9926 | | mstore(0x60, 0x80) 9927 | | mstore(0x80, 0xc0) 9928 | | writeString(0xa0, p2) 9929 | | writeString(0xe0, p3) 9930 | | } 9931 | | _sendLogPayload(0x1c, 0x104); 9932 | | /// @solidity memory-safe-assembly 9933 | | assembly { 9934 | | mstore(0x00, m0) 9935 | | mstore(0x20, m1) 9936 | | mstore(0x40, m2) 9937 | | mstore(0x60, m3) 9938 | | mstore(0x80, m4) 9939 | | mstore(0xa0, m5) 9940 | | mstore(0xc0, m6) 9941 | | mstore(0xe0, m7) 9942 | | mstore(0x100, m8) 9943 | | } 9944 | | } 9945 | | 9946 | | function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure { 9947 | | bytes32 m0; 9948 | | bytes32 m1; 9949 | | bytes32 m2; 9950 | | bytes32 m3; 9951 | | bytes32 m4; 9952 | | bytes32 m5; 9953 | | bytes32 m6; 9954 | | /// @solidity memory-safe-assembly 9955 | | assembly { 9956 | | function writeString(pos, w) { 9957 | | let length := 0 9958 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 9959 | | mstore(pos, length) 9960 | | let shift := sub(256, shl(3, length)) 9961 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 9962 | | } 9963 | | m0 := mload(0x00) 9964 | | m1 := mload(0x20) 9965 | | m2 := mload(0x40) 9966 | | m3 := mload(0x60) 9967 | | m4 := mload(0x80) 9968 | | m5 := mload(0xa0) 9969 | | m6 := mload(0xc0) 9970 | | // Selector of `log(uint256,string,address,address)`. 9971 | | mstore(0x00, 0x6168ed61) 9972 | | mstore(0x20, p0) 9973 | | mstore(0x40, 0x80) 9974 | | mstore(0x60, p2) 9975 | | mstore(0x80, p3) 9976 | | writeString(0xa0, p1) 9977 | | } 9978 | | _sendLogPayload(0x1c, 0xc4); 9979 | | /// @solidity memory-safe-assembly 9980 | | assembly { 9981 | | mstore(0x00, m0) 9982 | | mstore(0x20, m1) 9983 | | mstore(0x40, m2) 9984 | | mstore(0x60, m3) 9985 | | mstore(0x80, m4) 9986 | | mstore(0xa0, m5) 9987 | | mstore(0xc0, m6) 9988 | | } 9989 | | } 9990 | | 9991 | | function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure { 9992 | | bytes32 m0; 9993 | | bytes32 m1; 9994 | | bytes32 m2; 9995 | | bytes32 m3; 9996 | | bytes32 m4; 9997 | | bytes32 m5; 9998 | | bytes32 m6; 9999 | | /// @solidity memory-safe-assembly 10000 | | assembly { 10001 | | function writeString(pos, w) { 10002 | | let length := 0 10003 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10004 | | mstore(pos, length) 10005 | | let shift := sub(256, shl(3, length)) 10006 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10007 | | } 10008 | | m0 := mload(0x00) 10009 | | m1 := mload(0x20) 10010 | | m2 := mload(0x40) 10011 | | m3 := mload(0x60) 10012 | | m4 := mload(0x80) 10013 | | m5 := mload(0xa0) 10014 | | m6 := mload(0xc0) 10015 | | // Selector of `log(uint256,string,address,bool)`. 10016 | | mstore(0x00, 0x90c30a56) 10017 | | mstore(0x20, p0) 10018 | | mstore(0x40, 0x80) 10019 | | mstore(0x60, p2) 10020 | | mstore(0x80, p3) 10021 | | writeString(0xa0, p1) 10022 | | } 10023 | | _sendLogPayload(0x1c, 0xc4); 10024 | | /// @solidity memory-safe-assembly 10025 | | assembly { 10026 | | mstore(0x00, m0) 10027 | | mstore(0x20, m1) 10028 | | mstore(0x40, m2) 10029 | | mstore(0x60, m3) 10030 | | mstore(0x80, m4) 10031 | | mstore(0xa0, m5) 10032 | | mstore(0xc0, m6) 10033 | | } 10034 | | } 10035 | | 10036 | | function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure { 10037 | | bytes32 m0; 10038 | | bytes32 m1; 10039 | | bytes32 m2; 10040 | | bytes32 m3; 10041 | | bytes32 m4; 10042 | | bytes32 m5; 10043 | | bytes32 m6; 10044 | | /// @solidity memory-safe-assembly 10045 | | assembly { 10046 | | function writeString(pos, w) { 10047 | | let length := 0 10048 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10049 | | mstore(pos, length) 10050 | | let shift := sub(256, shl(3, length)) 10051 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10052 | | } 10053 | | m0 := mload(0x00) 10054 | | m1 := mload(0x20) 10055 | | m2 := mload(0x40) 10056 | | m3 := mload(0x60) 10057 | | m4 := mload(0x80) 10058 | | m5 := mload(0xa0) 10059 | | m6 := mload(0xc0) 10060 | | // Selector of `log(uint256,string,address,uint256)`. 10061 | | mstore(0x00, 0xe8d3018d) 10062 | | mstore(0x20, p0) 10063 | | mstore(0x40, 0x80) 10064 | | mstore(0x60, p2) 10065 | | mstore(0x80, p3) 10066 | | writeString(0xa0, p1) 10067 | | } 10068 | | _sendLogPayload(0x1c, 0xc4); 10069 | | /// @solidity memory-safe-assembly 10070 | | assembly { 10071 | | mstore(0x00, m0) 10072 | | mstore(0x20, m1) 10073 | | mstore(0x40, m2) 10074 | | mstore(0x60, m3) 10075 | | mstore(0x80, m4) 10076 | | mstore(0xa0, m5) 10077 | | mstore(0xc0, m6) 10078 | | } 10079 | | } 10080 | | 10081 | | function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure { 10082 | | bytes32 m0; 10083 | | bytes32 m1; 10084 | | bytes32 m2; 10085 | | bytes32 m3; 10086 | | bytes32 m4; 10087 | | bytes32 m5; 10088 | | bytes32 m6; 10089 | | bytes32 m7; 10090 | | bytes32 m8; 10091 | | /// @solidity memory-safe-assembly 10092 | | assembly { 10093 | | function writeString(pos, w) { 10094 | | let length := 0 10095 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10096 | | mstore(pos, length) 10097 | | let shift := sub(256, shl(3, length)) 10098 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10099 | | } 10100 | | m0 := mload(0x00) 10101 | | m1 := mload(0x20) 10102 | | m2 := mload(0x40) 10103 | | m3 := mload(0x60) 10104 | | m4 := mload(0x80) 10105 | | m5 := mload(0xa0) 10106 | | m6 := mload(0xc0) 10107 | | m7 := mload(0xe0) 10108 | | m8 := mload(0x100) 10109 | | // Selector of `log(uint256,string,address,string)`. 10110 | | mstore(0x00, 0x9c3adfa1) 10111 | | mstore(0x20, p0) 10112 | | mstore(0x40, 0x80) 10113 | | mstore(0x60, p2) 10114 | | mstore(0x80, 0xc0) 10115 | | writeString(0xa0, p1) 10116 | | writeString(0xe0, p3) 10117 | | } 10118 | | _sendLogPayload(0x1c, 0x104); 10119 | | /// @solidity memory-safe-assembly 10120 | | assembly { 10121 | | mstore(0x00, m0) 10122 | | mstore(0x20, m1) 10123 | | mstore(0x40, m2) 10124 | | mstore(0x60, m3) 10125 | | mstore(0x80, m4) 10126 | | mstore(0xa0, m5) 10127 | | mstore(0xc0, m6) 10128 | | mstore(0xe0, m7) 10129 | | mstore(0x100, m8) 10130 | | } 10131 | | } 10132 | | 10133 | | function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure { 10134 | | bytes32 m0; 10135 | | bytes32 m1; 10136 | | bytes32 m2; 10137 | | bytes32 m3; 10138 | | bytes32 m4; 10139 | | bytes32 m5; 10140 | | bytes32 m6; 10141 | | /// @solidity memory-safe-assembly 10142 | | assembly { 10143 | | function writeString(pos, w) { 10144 | | let length := 0 10145 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10146 | | mstore(pos, length) 10147 | | let shift := sub(256, shl(3, length)) 10148 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10149 | | } 10150 | | m0 := mload(0x00) 10151 | | m1 := mload(0x20) 10152 | | m2 := mload(0x40) 10153 | | m3 := mload(0x60) 10154 | | m4 := mload(0x80) 10155 | | m5 := mload(0xa0) 10156 | | m6 := mload(0xc0) 10157 | | // Selector of `log(uint256,string,bool,address)`. 10158 | | mstore(0x00, 0xae2ec581) 10159 | | mstore(0x20, p0) 10160 | | mstore(0x40, 0x80) 10161 | | mstore(0x60, p2) 10162 | | mstore(0x80, p3) 10163 | | writeString(0xa0, p1) 10164 | | } 10165 | | _sendLogPayload(0x1c, 0xc4); 10166 | | /// @solidity memory-safe-assembly 10167 | | assembly { 10168 | | mstore(0x00, m0) 10169 | | mstore(0x20, m1) 10170 | | mstore(0x40, m2) 10171 | | mstore(0x60, m3) 10172 | | mstore(0x80, m4) 10173 | | mstore(0xa0, m5) 10174 | | mstore(0xc0, m6) 10175 | | } 10176 | | } 10177 | | 10178 | | function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure { 10179 | | bytes32 m0; 10180 | | bytes32 m1; 10181 | | bytes32 m2; 10182 | | bytes32 m3; 10183 | | bytes32 m4; 10184 | | bytes32 m5; 10185 | | bytes32 m6; 10186 | | /// @solidity memory-safe-assembly 10187 | | assembly { 10188 | | function writeString(pos, w) { 10189 | | let length := 0 10190 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10191 | | mstore(pos, length) 10192 | | let shift := sub(256, shl(3, length)) 10193 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10194 | | } 10195 | | m0 := mload(0x00) 10196 | | m1 := mload(0x20) 10197 | | m2 := mload(0x40) 10198 | | m3 := mload(0x60) 10199 | | m4 := mload(0x80) 10200 | | m5 := mload(0xa0) 10201 | | m6 := mload(0xc0) 10202 | | // Selector of `log(uint256,string,bool,bool)`. 10203 | | mstore(0x00, 0xba535d9c) 10204 | | mstore(0x20, p0) 10205 | | mstore(0x40, 0x80) 10206 | | mstore(0x60, p2) 10207 | | mstore(0x80, p3) 10208 | | writeString(0xa0, p1) 10209 | | } 10210 | | _sendLogPayload(0x1c, 0xc4); 10211 | | /// @solidity memory-safe-assembly 10212 | | assembly { 10213 | | mstore(0x00, m0) 10214 | | mstore(0x20, m1) 10215 | | mstore(0x40, m2) 10216 | | mstore(0x60, m3) 10217 | | mstore(0x80, m4) 10218 | | mstore(0xa0, m5) 10219 | | mstore(0xc0, m6) 10220 | | } 10221 | | } 10222 | | 10223 | | function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure { 10224 | | bytes32 m0; 10225 | | bytes32 m1; 10226 | | bytes32 m2; 10227 | | bytes32 m3; 10228 | | bytes32 m4; 10229 | | bytes32 m5; 10230 | | bytes32 m6; 10231 | | /// @solidity memory-safe-assembly 10232 | | assembly { 10233 | | function writeString(pos, w) { 10234 | | let length := 0 10235 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10236 | | mstore(pos, length) 10237 | | let shift := sub(256, shl(3, length)) 10238 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10239 | | } 10240 | | m0 := mload(0x00) 10241 | | m1 := mload(0x20) 10242 | | m2 := mload(0x40) 10243 | | m3 := mload(0x60) 10244 | | m4 := mload(0x80) 10245 | | m5 := mload(0xa0) 10246 | | m6 := mload(0xc0) 10247 | | // Selector of `log(uint256,string,bool,uint256)`. 10248 | | mstore(0x00, 0xcf009880) 10249 | | mstore(0x20, p0) 10250 | | mstore(0x40, 0x80) 10251 | | mstore(0x60, p2) 10252 | | mstore(0x80, p3) 10253 | | writeString(0xa0, p1) 10254 | | } 10255 | | _sendLogPayload(0x1c, 0xc4); 10256 | | /// @solidity memory-safe-assembly 10257 | | assembly { 10258 | | mstore(0x00, m0) 10259 | | mstore(0x20, m1) 10260 | | mstore(0x40, m2) 10261 | | mstore(0x60, m3) 10262 | | mstore(0x80, m4) 10263 | | mstore(0xa0, m5) 10264 | | mstore(0xc0, m6) 10265 | | } 10266 | | } 10267 | | 10268 | | function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { 10269 | | bytes32 m0; 10270 | | bytes32 m1; 10271 | | bytes32 m2; 10272 | | bytes32 m3; 10273 | | bytes32 m4; 10274 | | bytes32 m5; 10275 | | bytes32 m6; 10276 | | bytes32 m7; 10277 | | bytes32 m8; 10278 | | /// @solidity memory-safe-assembly 10279 | | assembly { 10280 | | function writeString(pos, w) { 10281 | | let length := 0 10282 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10283 | | mstore(pos, length) 10284 | | let shift := sub(256, shl(3, length)) 10285 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10286 | | } 10287 | | m0 := mload(0x00) 10288 | | m1 := mload(0x20) 10289 | | m2 := mload(0x40) 10290 | | m3 := mload(0x60) 10291 | | m4 := mload(0x80) 10292 | | m5 := mload(0xa0) 10293 | | m6 := mload(0xc0) 10294 | | m7 := mload(0xe0) 10295 | | m8 := mload(0x100) 10296 | | // Selector of `log(uint256,string,bool,string)`. 10297 | | mstore(0x00, 0xd2d423cd) 10298 | | mstore(0x20, p0) 10299 | | mstore(0x40, 0x80) 10300 | | mstore(0x60, p2) 10301 | | mstore(0x80, 0xc0) 10302 | | writeString(0xa0, p1) 10303 | | writeString(0xe0, p3) 10304 | | } 10305 | | _sendLogPayload(0x1c, 0x104); 10306 | | /// @solidity memory-safe-assembly 10307 | | assembly { 10308 | | mstore(0x00, m0) 10309 | | mstore(0x20, m1) 10310 | | mstore(0x40, m2) 10311 | | mstore(0x60, m3) 10312 | | mstore(0x80, m4) 10313 | | mstore(0xa0, m5) 10314 | | mstore(0xc0, m6) 10315 | | mstore(0xe0, m7) 10316 | | mstore(0x100, m8) 10317 | | } 10318 | | } 10319 | | 10320 | | function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure { 10321 | | bytes32 m0; 10322 | | bytes32 m1; 10323 | | bytes32 m2; 10324 | | bytes32 m3; 10325 | | bytes32 m4; 10326 | | bytes32 m5; 10327 | | bytes32 m6; 10328 | | /// @solidity memory-safe-assembly 10329 | | assembly { 10330 | | function writeString(pos, w) { 10331 | | let length := 0 10332 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10333 | | mstore(pos, length) 10334 | | let shift := sub(256, shl(3, length)) 10335 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10336 | | } 10337 | | m0 := mload(0x00) 10338 | | m1 := mload(0x20) 10339 | | m2 := mload(0x40) 10340 | | m3 := mload(0x60) 10341 | | m4 := mload(0x80) 10342 | | m5 := mload(0xa0) 10343 | | m6 := mload(0xc0) 10344 | | // Selector of `log(uint256,string,uint256,address)`. 10345 | | mstore(0x00, 0x3b2279b4) 10346 | | mstore(0x20, p0) 10347 | | mstore(0x40, 0x80) 10348 | | mstore(0x60, p2) 10349 | | mstore(0x80, p3) 10350 | | writeString(0xa0, p1) 10351 | | } 10352 | | _sendLogPayload(0x1c, 0xc4); 10353 | | /// @solidity memory-safe-assembly 10354 | | assembly { 10355 | | mstore(0x00, m0) 10356 | | mstore(0x20, m1) 10357 | | mstore(0x40, m2) 10358 | | mstore(0x60, m3) 10359 | | mstore(0x80, m4) 10360 | | mstore(0xa0, m5) 10361 | | mstore(0xc0, m6) 10362 | | } 10363 | | } 10364 | | 10365 | | function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure { 10366 | | bytes32 m0; 10367 | | bytes32 m1; 10368 | | bytes32 m2; 10369 | | bytes32 m3; 10370 | | bytes32 m4; 10371 | | bytes32 m5; 10372 | | bytes32 m6; 10373 | | /// @solidity memory-safe-assembly 10374 | | assembly { 10375 | | function writeString(pos, w) { 10376 | | let length := 0 10377 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10378 | | mstore(pos, length) 10379 | | let shift := sub(256, shl(3, length)) 10380 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10381 | | } 10382 | | m0 := mload(0x00) 10383 | | m1 := mload(0x20) 10384 | | m2 := mload(0x40) 10385 | | m3 := mload(0x60) 10386 | | m4 := mload(0x80) 10387 | | m5 := mload(0xa0) 10388 | | m6 := mload(0xc0) 10389 | | // Selector of `log(uint256,string,uint256,bool)`. 10390 | | mstore(0x00, 0x691a8f74) 10391 | | mstore(0x20, p0) 10392 | | mstore(0x40, 0x80) 10393 | | mstore(0x60, p2) 10394 | | mstore(0x80, p3) 10395 | | writeString(0xa0, p1) 10396 | | } 10397 | | _sendLogPayload(0x1c, 0xc4); 10398 | | /// @solidity memory-safe-assembly 10399 | | assembly { 10400 | | mstore(0x00, m0) 10401 | | mstore(0x20, m1) 10402 | | mstore(0x40, m2) 10403 | | mstore(0x60, m3) 10404 | | mstore(0x80, m4) 10405 | | mstore(0xa0, m5) 10406 | | mstore(0xc0, m6) 10407 | | } 10408 | | } 10409 | | 10410 | | function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { 10411 | | bytes32 m0; 10412 | | bytes32 m1; 10413 | | bytes32 m2; 10414 | | bytes32 m3; 10415 | | bytes32 m4; 10416 | | bytes32 m5; 10417 | | bytes32 m6; 10418 | | /// @solidity memory-safe-assembly 10419 | | assembly { 10420 | | function writeString(pos, w) { 10421 | | let length := 0 10422 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10423 | | mstore(pos, length) 10424 | | let shift := sub(256, shl(3, length)) 10425 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10426 | | } 10427 | | m0 := mload(0x00) 10428 | | m1 := mload(0x20) 10429 | | m2 := mload(0x40) 10430 | | m3 := mload(0x60) 10431 | | m4 := mload(0x80) 10432 | | m5 := mload(0xa0) 10433 | | m6 := mload(0xc0) 10434 | | // Selector of `log(uint256,string,uint256,uint256)`. 10435 | | mstore(0x00, 0x82c25b74) 10436 | | mstore(0x20, p0) 10437 | | mstore(0x40, 0x80) 10438 | | mstore(0x60, p2) 10439 | | mstore(0x80, p3) 10440 | | writeString(0xa0, p1) 10441 | | } 10442 | | _sendLogPayload(0x1c, 0xc4); 10443 | | /// @solidity memory-safe-assembly 10444 | | assembly { 10445 | | mstore(0x00, m0) 10446 | | mstore(0x20, m1) 10447 | | mstore(0x40, m2) 10448 | | mstore(0x60, m3) 10449 | | mstore(0x80, m4) 10450 | | mstore(0xa0, m5) 10451 | | mstore(0xc0, m6) 10452 | | } 10453 | | } 10454 | | 10455 | | function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { 10456 | | bytes32 m0; 10457 | | bytes32 m1; 10458 | | bytes32 m2; 10459 | | bytes32 m3; 10460 | | bytes32 m4; 10461 | | bytes32 m5; 10462 | | bytes32 m6; 10463 | | bytes32 m7; 10464 | | bytes32 m8; 10465 | | /// @solidity memory-safe-assembly 10466 | | assembly { 10467 | | function writeString(pos, w) { 10468 | | let length := 0 10469 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10470 | | mstore(pos, length) 10471 | | let shift := sub(256, shl(3, length)) 10472 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10473 | | } 10474 | | m0 := mload(0x00) 10475 | | m1 := mload(0x20) 10476 | | m2 := mload(0x40) 10477 | | m3 := mload(0x60) 10478 | | m4 := mload(0x80) 10479 | | m5 := mload(0xa0) 10480 | | m6 := mload(0xc0) 10481 | | m7 := mload(0xe0) 10482 | | m8 := mload(0x100) 10483 | | // Selector of `log(uint256,string,uint256,string)`. 10484 | | mstore(0x00, 0xb7b914ca) 10485 | | mstore(0x20, p0) 10486 | | mstore(0x40, 0x80) 10487 | | mstore(0x60, p2) 10488 | | mstore(0x80, 0xc0) 10489 | | writeString(0xa0, p1) 10490 | | writeString(0xe0, p3) 10491 | | } 10492 | | _sendLogPayload(0x1c, 0x104); 10493 | | /// @solidity memory-safe-assembly 10494 | | assembly { 10495 | | mstore(0x00, m0) 10496 | | mstore(0x20, m1) 10497 | | mstore(0x40, m2) 10498 | | mstore(0x60, m3) 10499 | | mstore(0x80, m4) 10500 | | mstore(0xa0, m5) 10501 | | mstore(0xc0, m6) 10502 | | mstore(0xe0, m7) 10503 | | mstore(0x100, m8) 10504 | | } 10505 | | } 10506 | | 10507 | | function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure { 10508 | | bytes32 m0; 10509 | | bytes32 m1; 10510 | | bytes32 m2; 10511 | | bytes32 m3; 10512 | | bytes32 m4; 10513 | | bytes32 m5; 10514 | | bytes32 m6; 10515 | | bytes32 m7; 10516 | | bytes32 m8; 10517 | | /// @solidity memory-safe-assembly 10518 | | assembly { 10519 | | function writeString(pos, w) { 10520 | | let length := 0 10521 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10522 | | mstore(pos, length) 10523 | | let shift := sub(256, shl(3, length)) 10524 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10525 | | } 10526 | | m0 := mload(0x00) 10527 | | m1 := mload(0x20) 10528 | | m2 := mload(0x40) 10529 | | m3 := mload(0x60) 10530 | | m4 := mload(0x80) 10531 | | m5 := mload(0xa0) 10532 | | m6 := mload(0xc0) 10533 | | m7 := mload(0xe0) 10534 | | m8 := mload(0x100) 10535 | | // Selector of `log(uint256,string,string,address)`. 10536 | | mstore(0x00, 0xd583c602) 10537 | | mstore(0x20, p0) 10538 | | mstore(0x40, 0x80) 10539 | | mstore(0x60, 0xc0) 10540 | | mstore(0x80, p3) 10541 | | writeString(0xa0, p1) 10542 | | writeString(0xe0, p2) 10543 | | } 10544 | | _sendLogPayload(0x1c, 0x104); 10545 | | /// @solidity memory-safe-assembly 10546 | | assembly { 10547 | | mstore(0x00, m0) 10548 | | mstore(0x20, m1) 10549 | | mstore(0x40, m2) 10550 | | mstore(0x60, m3) 10551 | | mstore(0x80, m4) 10552 | | mstore(0xa0, m5) 10553 | | mstore(0xc0, m6) 10554 | | mstore(0xe0, m7) 10555 | | mstore(0x100, m8) 10556 | | } 10557 | | } 10558 | | 10559 | | function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { 10560 | | bytes32 m0; 10561 | | bytes32 m1; 10562 | | bytes32 m2; 10563 | | bytes32 m3; 10564 | | bytes32 m4; 10565 | | bytes32 m5; 10566 | | bytes32 m6; 10567 | | bytes32 m7; 10568 | | bytes32 m8; 10569 | | /// @solidity memory-safe-assembly 10570 | | assembly { 10571 | | function writeString(pos, w) { 10572 | | let length := 0 10573 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10574 | | mstore(pos, length) 10575 | | let shift := sub(256, shl(3, length)) 10576 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10577 | | } 10578 | | m0 := mload(0x00) 10579 | | m1 := mload(0x20) 10580 | | m2 := mload(0x40) 10581 | | m3 := mload(0x60) 10582 | | m4 := mload(0x80) 10583 | | m5 := mload(0xa0) 10584 | | m6 := mload(0xc0) 10585 | | m7 := mload(0xe0) 10586 | | m8 := mload(0x100) 10587 | | // Selector of `log(uint256,string,string,bool)`. 10588 | | mstore(0x00, 0xb3a6b6bd) 10589 | | mstore(0x20, p0) 10590 | | mstore(0x40, 0x80) 10591 | | mstore(0x60, 0xc0) 10592 | | mstore(0x80, p3) 10593 | | writeString(0xa0, p1) 10594 | | writeString(0xe0, p2) 10595 | | } 10596 | | _sendLogPayload(0x1c, 0x104); 10597 | | /// @solidity memory-safe-assembly 10598 | | assembly { 10599 | | mstore(0x00, m0) 10600 | | mstore(0x20, m1) 10601 | | mstore(0x40, m2) 10602 | | mstore(0x60, m3) 10603 | | mstore(0x80, m4) 10604 | | mstore(0xa0, m5) 10605 | | mstore(0xc0, m6) 10606 | | mstore(0xe0, m7) 10607 | | mstore(0x100, m8) 10608 | | } 10609 | | } 10610 | | 10611 | | function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { 10612 | | bytes32 m0; 10613 | | bytes32 m1; 10614 | | bytes32 m2; 10615 | | bytes32 m3; 10616 | | bytes32 m4; 10617 | | bytes32 m5; 10618 | | bytes32 m6; 10619 | | bytes32 m7; 10620 | | bytes32 m8; 10621 | | /// @solidity memory-safe-assembly 10622 | | assembly { 10623 | | function writeString(pos, w) { 10624 | | let length := 0 10625 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10626 | | mstore(pos, length) 10627 | | let shift := sub(256, shl(3, length)) 10628 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10629 | | } 10630 | | m0 := mload(0x00) 10631 | | m1 := mload(0x20) 10632 | | m2 := mload(0x40) 10633 | | m3 := mload(0x60) 10634 | | m4 := mload(0x80) 10635 | | m5 := mload(0xa0) 10636 | | m6 := mload(0xc0) 10637 | | m7 := mload(0xe0) 10638 | | m8 := mload(0x100) 10639 | | // Selector of `log(uint256,string,string,uint256)`. 10640 | | mstore(0x00, 0xb028c9bd) 10641 | | mstore(0x20, p0) 10642 | | mstore(0x40, 0x80) 10643 | | mstore(0x60, 0xc0) 10644 | | mstore(0x80, p3) 10645 | | writeString(0xa0, p1) 10646 | | writeString(0xe0, p2) 10647 | | } 10648 | | _sendLogPayload(0x1c, 0x104); 10649 | | /// @solidity memory-safe-assembly 10650 | | assembly { 10651 | | mstore(0x00, m0) 10652 | | mstore(0x20, m1) 10653 | | mstore(0x40, m2) 10654 | | mstore(0x60, m3) 10655 | | mstore(0x80, m4) 10656 | | mstore(0xa0, m5) 10657 | | mstore(0xc0, m6) 10658 | | mstore(0xe0, m7) 10659 | | mstore(0x100, m8) 10660 | | } 10661 | | } 10662 | | 10663 | | function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { 10664 | | bytes32 m0; 10665 | | bytes32 m1; 10666 | | bytes32 m2; 10667 | | bytes32 m3; 10668 | | bytes32 m4; 10669 | | bytes32 m5; 10670 | | bytes32 m6; 10671 | | bytes32 m7; 10672 | | bytes32 m8; 10673 | | bytes32 m9; 10674 | | bytes32 m10; 10675 | | /// @solidity memory-safe-assembly 10676 | | assembly { 10677 | | function writeString(pos, w) { 10678 | | let length := 0 10679 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10680 | | mstore(pos, length) 10681 | | let shift := sub(256, shl(3, length)) 10682 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10683 | | } 10684 | | m0 := mload(0x00) 10685 | | m1 := mload(0x20) 10686 | | m2 := mload(0x40) 10687 | | m3 := mload(0x60) 10688 | | m4 := mload(0x80) 10689 | | m5 := mload(0xa0) 10690 | | m6 := mload(0xc0) 10691 | | m7 := mload(0xe0) 10692 | | m8 := mload(0x100) 10693 | | m9 := mload(0x120) 10694 | | m10 := mload(0x140) 10695 | | // Selector of `log(uint256,string,string,string)`. 10696 | | mstore(0x00, 0x21ad0683) 10697 | | mstore(0x20, p0) 10698 | | mstore(0x40, 0x80) 10699 | | mstore(0x60, 0xc0) 10700 | | mstore(0x80, 0x100) 10701 | | writeString(0xa0, p1) 10702 | | writeString(0xe0, p2) 10703 | | writeString(0x120, p3) 10704 | | } 10705 | | _sendLogPayload(0x1c, 0x144); 10706 | | /// @solidity memory-safe-assembly 10707 | | assembly { 10708 | | mstore(0x00, m0) 10709 | | mstore(0x20, m1) 10710 | | mstore(0x40, m2) 10711 | | mstore(0x60, m3) 10712 | | mstore(0x80, m4) 10713 | | mstore(0xa0, m5) 10714 | | mstore(0xc0, m6) 10715 | | mstore(0xe0, m7) 10716 | | mstore(0x100, m8) 10717 | | mstore(0x120, m9) 10718 | | mstore(0x140, m10) 10719 | | } 10720 | | } 10721 | | 10722 | | function log(bytes32 p0, address p1, address p2, address p3) internal pure { 10723 | | bytes32 m0; 10724 | | bytes32 m1; 10725 | | bytes32 m2; 10726 | | bytes32 m3; 10727 | | bytes32 m4; 10728 | | bytes32 m5; 10729 | | bytes32 m6; 10730 | | /// @solidity memory-safe-assembly 10731 | | assembly { 10732 | | function writeString(pos, w) { 10733 | | let length := 0 10734 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10735 | | mstore(pos, length) 10736 | | let shift := sub(256, shl(3, length)) 10737 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10738 | | } 10739 | | m0 := mload(0x00) 10740 | | m1 := mload(0x20) 10741 | | m2 := mload(0x40) 10742 | | m3 := mload(0x60) 10743 | | m4 := mload(0x80) 10744 | | m5 := mload(0xa0) 10745 | | m6 := mload(0xc0) 10746 | | // Selector of `log(string,address,address,address)`. 10747 | | mstore(0x00, 0xed8f28f6) 10748 | | mstore(0x20, 0x80) 10749 | | mstore(0x40, p1) 10750 | | mstore(0x60, p2) 10751 | | mstore(0x80, p3) 10752 | | writeString(0xa0, p0) 10753 | | } 10754 | | _sendLogPayload(0x1c, 0xc4); 10755 | | /// @solidity memory-safe-assembly 10756 | | assembly { 10757 | | mstore(0x00, m0) 10758 | | mstore(0x20, m1) 10759 | | mstore(0x40, m2) 10760 | | mstore(0x60, m3) 10761 | | mstore(0x80, m4) 10762 | | mstore(0xa0, m5) 10763 | | mstore(0xc0, m6) 10764 | | } 10765 | | } 10766 | | 10767 | | function log(bytes32 p0, address p1, address p2, bool p3) internal pure { 10768 | | bytes32 m0; 10769 | | bytes32 m1; 10770 | | bytes32 m2; 10771 | | bytes32 m3; 10772 | | bytes32 m4; 10773 | | bytes32 m5; 10774 | | bytes32 m6; 10775 | | /// @solidity memory-safe-assembly 10776 | | assembly { 10777 | | function writeString(pos, w) { 10778 | | let length := 0 10779 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10780 | | mstore(pos, length) 10781 | | let shift := sub(256, shl(3, length)) 10782 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10783 | | } 10784 | | m0 := mload(0x00) 10785 | | m1 := mload(0x20) 10786 | | m2 := mload(0x40) 10787 | | m3 := mload(0x60) 10788 | | m4 := mload(0x80) 10789 | | m5 := mload(0xa0) 10790 | | m6 := mload(0xc0) 10791 | | // Selector of `log(string,address,address,bool)`. 10792 | | mstore(0x00, 0xb59dbd60) 10793 | | mstore(0x20, 0x80) 10794 | | mstore(0x40, p1) 10795 | | mstore(0x60, p2) 10796 | | mstore(0x80, p3) 10797 | | writeString(0xa0, p0) 10798 | | } 10799 | | _sendLogPayload(0x1c, 0xc4); 10800 | | /// @solidity memory-safe-assembly 10801 | | assembly { 10802 | | mstore(0x00, m0) 10803 | | mstore(0x20, m1) 10804 | | mstore(0x40, m2) 10805 | | mstore(0x60, m3) 10806 | | mstore(0x80, m4) 10807 | | mstore(0xa0, m5) 10808 | | mstore(0xc0, m6) 10809 | | } 10810 | | } 10811 | | 10812 | | function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure { 10813 | | bytes32 m0; 10814 | | bytes32 m1; 10815 | | bytes32 m2; 10816 | | bytes32 m3; 10817 | | bytes32 m4; 10818 | | bytes32 m5; 10819 | | bytes32 m6; 10820 | | /// @solidity memory-safe-assembly 10821 | | assembly { 10822 | | function writeString(pos, w) { 10823 | | let length := 0 10824 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10825 | | mstore(pos, length) 10826 | | let shift := sub(256, shl(3, length)) 10827 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10828 | | } 10829 | | m0 := mload(0x00) 10830 | | m1 := mload(0x20) 10831 | | m2 := mload(0x40) 10832 | | m3 := mload(0x60) 10833 | | m4 := mload(0x80) 10834 | | m5 := mload(0xa0) 10835 | | m6 := mload(0xc0) 10836 | | // Selector of `log(string,address,address,uint256)`. 10837 | | mstore(0x00, 0x8ef3f399) 10838 | | mstore(0x20, 0x80) 10839 | | mstore(0x40, p1) 10840 | | mstore(0x60, p2) 10841 | | mstore(0x80, p3) 10842 | | writeString(0xa0, p0) 10843 | | } 10844 | | _sendLogPayload(0x1c, 0xc4); 10845 | | /// @solidity memory-safe-assembly 10846 | | assembly { 10847 | | mstore(0x00, m0) 10848 | | mstore(0x20, m1) 10849 | | mstore(0x40, m2) 10850 | | mstore(0x60, m3) 10851 | | mstore(0x80, m4) 10852 | | mstore(0xa0, m5) 10853 | | mstore(0xc0, m6) 10854 | | } 10855 | | } 10856 | | 10857 | | function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure { 10858 | | bytes32 m0; 10859 | | bytes32 m1; 10860 | | bytes32 m2; 10861 | | bytes32 m3; 10862 | | bytes32 m4; 10863 | | bytes32 m5; 10864 | | bytes32 m6; 10865 | | bytes32 m7; 10866 | | bytes32 m8; 10867 | | /// @solidity memory-safe-assembly 10868 | | assembly { 10869 | | function writeString(pos, w) { 10870 | | let length := 0 10871 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10872 | | mstore(pos, length) 10873 | | let shift := sub(256, shl(3, length)) 10874 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10875 | | } 10876 | | m0 := mload(0x00) 10877 | | m1 := mload(0x20) 10878 | | m2 := mload(0x40) 10879 | | m3 := mload(0x60) 10880 | | m4 := mload(0x80) 10881 | | m5 := mload(0xa0) 10882 | | m6 := mload(0xc0) 10883 | | m7 := mload(0xe0) 10884 | | m8 := mload(0x100) 10885 | | // Selector of `log(string,address,address,string)`. 10886 | | mstore(0x00, 0x800a1c67) 10887 | | mstore(0x20, 0x80) 10888 | | mstore(0x40, p1) 10889 | | mstore(0x60, p2) 10890 | | mstore(0x80, 0xc0) 10891 | | writeString(0xa0, p0) 10892 | | writeString(0xe0, p3) 10893 | | } 10894 | | _sendLogPayload(0x1c, 0x104); 10895 | | /// @solidity memory-safe-assembly 10896 | | assembly { 10897 | | mstore(0x00, m0) 10898 | | mstore(0x20, m1) 10899 | | mstore(0x40, m2) 10900 | | mstore(0x60, m3) 10901 | | mstore(0x80, m4) 10902 | | mstore(0xa0, m5) 10903 | | mstore(0xc0, m6) 10904 | | mstore(0xe0, m7) 10905 | | mstore(0x100, m8) 10906 | | } 10907 | | } 10908 | | 10909 | | function log(bytes32 p0, address p1, bool p2, address p3) internal pure { 10910 | | bytes32 m0; 10911 | | bytes32 m1; 10912 | | bytes32 m2; 10913 | | bytes32 m3; 10914 | | bytes32 m4; 10915 | | bytes32 m5; 10916 | | bytes32 m6; 10917 | | /// @solidity memory-safe-assembly 10918 | | assembly { 10919 | | function writeString(pos, w) { 10920 | | let length := 0 10921 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10922 | | mstore(pos, length) 10923 | | let shift := sub(256, shl(3, length)) 10924 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10925 | | } 10926 | | m0 := mload(0x00) 10927 | | m1 := mload(0x20) 10928 | | m2 := mload(0x40) 10929 | | m3 := mload(0x60) 10930 | | m4 := mload(0x80) 10931 | | m5 := mload(0xa0) 10932 | | m6 := mload(0xc0) 10933 | | // Selector of `log(string,address,bool,address)`. 10934 | | mstore(0x00, 0x223603bd) 10935 | | mstore(0x20, 0x80) 10936 | | mstore(0x40, p1) 10937 | | mstore(0x60, p2) 10938 | | mstore(0x80, p3) 10939 | | writeString(0xa0, p0) 10940 | | } 10941 | | _sendLogPayload(0x1c, 0xc4); 10942 | | /// @solidity memory-safe-assembly 10943 | | assembly { 10944 | | mstore(0x00, m0) 10945 | | mstore(0x20, m1) 10946 | | mstore(0x40, m2) 10947 | | mstore(0x60, m3) 10948 | | mstore(0x80, m4) 10949 | | mstore(0xa0, m5) 10950 | | mstore(0xc0, m6) 10951 | | } 10952 | | } 10953 | | 10954 | | function log(bytes32 p0, address p1, bool p2, bool p3) internal pure { 10955 | | bytes32 m0; 10956 | | bytes32 m1; 10957 | | bytes32 m2; 10958 | | bytes32 m3; 10959 | | bytes32 m4; 10960 | | bytes32 m5; 10961 | | bytes32 m6; 10962 | | /// @solidity memory-safe-assembly 10963 | | assembly { 10964 | | function writeString(pos, w) { 10965 | | let length := 0 10966 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 10967 | | mstore(pos, length) 10968 | | let shift := sub(256, shl(3, length)) 10969 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 10970 | | } 10971 | | m0 := mload(0x00) 10972 | | m1 := mload(0x20) 10973 | | m2 := mload(0x40) 10974 | | m3 := mload(0x60) 10975 | | m4 := mload(0x80) 10976 | | m5 := mload(0xa0) 10977 | | m6 := mload(0xc0) 10978 | | // Selector of `log(string,address,bool,bool)`. 10979 | | mstore(0x00, 0x79884c2b) 10980 | | mstore(0x20, 0x80) 10981 | | mstore(0x40, p1) 10982 | | mstore(0x60, p2) 10983 | | mstore(0x80, p3) 10984 | | writeString(0xa0, p0) 10985 | | } 10986 | | _sendLogPayload(0x1c, 0xc4); 10987 | | /// @solidity memory-safe-assembly 10988 | | assembly { 10989 | | mstore(0x00, m0) 10990 | | mstore(0x20, m1) 10991 | | mstore(0x40, m2) 10992 | | mstore(0x60, m3) 10993 | | mstore(0x80, m4) 10994 | | mstore(0xa0, m5) 10995 | | mstore(0xc0, m6) 10996 | | } 10997 | | } 10998 | | 10999 | | function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure { 11000 | | bytes32 m0; 11001 | | bytes32 m1; 11002 | | bytes32 m2; 11003 | | bytes32 m3; 11004 | | bytes32 m4; 11005 | | bytes32 m5; 11006 | | bytes32 m6; 11007 | | /// @solidity memory-safe-assembly 11008 | | assembly { 11009 | | function writeString(pos, w) { 11010 | | let length := 0 11011 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11012 | | mstore(pos, length) 11013 | | let shift := sub(256, shl(3, length)) 11014 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11015 | | } 11016 | | m0 := mload(0x00) 11017 | | m1 := mload(0x20) 11018 | | m2 := mload(0x40) 11019 | | m3 := mload(0x60) 11020 | | m4 := mload(0x80) 11021 | | m5 := mload(0xa0) 11022 | | m6 := mload(0xc0) 11023 | | // Selector of `log(string,address,bool,uint256)`. 11024 | | mstore(0x00, 0x3e9f866a) 11025 | | mstore(0x20, 0x80) 11026 | | mstore(0x40, p1) 11027 | | mstore(0x60, p2) 11028 | | mstore(0x80, p3) 11029 | | writeString(0xa0, p0) 11030 | | } 11031 | | _sendLogPayload(0x1c, 0xc4); 11032 | | /// @solidity memory-safe-assembly 11033 | | assembly { 11034 | | mstore(0x00, m0) 11035 | | mstore(0x20, m1) 11036 | | mstore(0x40, m2) 11037 | | mstore(0x60, m3) 11038 | | mstore(0x80, m4) 11039 | | mstore(0xa0, m5) 11040 | | mstore(0xc0, m6) 11041 | | } 11042 | | } 11043 | | 11044 | | function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure { 11045 | | bytes32 m0; 11046 | | bytes32 m1; 11047 | | bytes32 m2; 11048 | | bytes32 m3; 11049 | | bytes32 m4; 11050 | | bytes32 m5; 11051 | | bytes32 m6; 11052 | | bytes32 m7; 11053 | | bytes32 m8; 11054 | | /// @solidity memory-safe-assembly 11055 | | assembly { 11056 | | function writeString(pos, w) { 11057 | | let length := 0 11058 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11059 | | mstore(pos, length) 11060 | | let shift := sub(256, shl(3, length)) 11061 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11062 | | } 11063 | | m0 := mload(0x00) 11064 | | m1 := mload(0x20) 11065 | | m2 := mload(0x40) 11066 | | m3 := mload(0x60) 11067 | | m4 := mload(0x80) 11068 | | m5 := mload(0xa0) 11069 | | m6 := mload(0xc0) 11070 | | m7 := mload(0xe0) 11071 | | m8 := mload(0x100) 11072 | | // Selector of `log(string,address,bool,string)`. 11073 | | mstore(0x00, 0x0454c079) 11074 | | mstore(0x20, 0x80) 11075 | | mstore(0x40, p1) 11076 | | mstore(0x60, p2) 11077 | | mstore(0x80, 0xc0) 11078 | | writeString(0xa0, p0) 11079 | | writeString(0xe0, p3) 11080 | | } 11081 | | _sendLogPayload(0x1c, 0x104); 11082 | | /// @solidity memory-safe-assembly 11083 | | assembly { 11084 | | mstore(0x00, m0) 11085 | | mstore(0x20, m1) 11086 | | mstore(0x40, m2) 11087 | | mstore(0x60, m3) 11088 | | mstore(0x80, m4) 11089 | | mstore(0xa0, m5) 11090 | | mstore(0xc0, m6) 11091 | | mstore(0xe0, m7) 11092 | | mstore(0x100, m8) 11093 | | } 11094 | | } 11095 | | 11096 | | function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure { 11097 | | bytes32 m0; 11098 | | bytes32 m1; 11099 | | bytes32 m2; 11100 | | bytes32 m3; 11101 | | bytes32 m4; 11102 | | bytes32 m5; 11103 | | bytes32 m6; 11104 | | /// @solidity memory-safe-assembly 11105 | | assembly { 11106 | | function writeString(pos, w) { 11107 | | let length := 0 11108 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11109 | | mstore(pos, length) 11110 | | let shift := sub(256, shl(3, length)) 11111 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11112 | | } 11113 | | m0 := mload(0x00) 11114 | | m1 := mload(0x20) 11115 | | m2 := mload(0x40) 11116 | | m3 := mload(0x60) 11117 | | m4 := mload(0x80) 11118 | | m5 := mload(0xa0) 11119 | | m6 := mload(0xc0) 11120 | | // Selector of `log(string,address,uint256,address)`. 11121 | | mstore(0x00, 0x63fb8bc5) 11122 | | mstore(0x20, 0x80) 11123 | | mstore(0x40, p1) 11124 | | mstore(0x60, p2) 11125 | | mstore(0x80, p3) 11126 | | writeString(0xa0, p0) 11127 | | } 11128 | | _sendLogPayload(0x1c, 0xc4); 11129 | | /// @solidity memory-safe-assembly 11130 | | assembly { 11131 | | mstore(0x00, m0) 11132 | | mstore(0x20, m1) 11133 | | mstore(0x40, m2) 11134 | | mstore(0x60, m3) 11135 | | mstore(0x80, m4) 11136 | | mstore(0xa0, m5) 11137 | | mstore(0xc0, m6) 11138 | | } 11139 | | } 11140 | | 11141 | | function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure { 11142 | | bytes32 m0; 11143 | | bytes32 m1; 11144 | | bytes32 m2; 11145 | | bytes32 m3; 11146 | | bytes32 m4; 11147 | | bytes32 m5; 11148 | | bytes32 m6; 11149 | | /// @solidity memory-safe-assembly 11150 | | assembly { 11151 | | function writeString(pos, w) { 11152 | | let length := 0 11153 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11154 | | mstore(pos, length) 11155 | | let shift := sub(256, shl(3, length)) 11156 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11157 | | } 11158 | | m0 := mload(0x00) 11159 | | m1 := mload(0x20) 11160 | | m2 := mload(0x40) 11161 | | m3 := mload(0x60) 11162 | | m4 := mload(0x80) 11163 | | m5 := mload(0xa0) 11164 | | m6 := mload(0xc0) 11165 | | // Selector of `log(string,address,uint256,bool)`. 11166 | | mstore(0x00, 0xfc4845f0) 11167 | | mstore(0x20, 0x80) 11168 | | mstore(0x40, p1) 11169 | | mstore(0x60, p2) 11170 | | mstore(0x80, p3) 11171 | | writeString(0xa0, p0) 11172 | | } 11173 | | _sendLogPayload(0x1c, 0xc4); 11174 | | /// @solidity memory-safe-assembly 11175 | | assembly { 11176 | | mstore(0x00, m0) 11177 | | mstore(0x20, m1) 11178 | | mstore(0x40, m2) 11179 | | mstore(0x60, m3) 11180 | | mstore(0x80, m4) 11181 | | mstore(0xa0, m5) 11182 | | mstore(0xc0, m6) 11183 | | } 11184 | | } 11185 | | 11186 | | function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure { 11187 | | bytes32 m0; 11188 | | bytes32 m1; 11189 | | bytes32 m2; 11190 | | bytes32 m3; 11191 | | bytes32 m4; 11192 | | bytes32 m5; 11193 | | bytes32 m6; 11194 | | /// @solidity memory-safe-assembly 11195 | | assembly { 11196 | | function writeString(pos, w) { 11197 | | let length := 0 11198 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11199 | | mstore(pos, length) 11200 | | let shift := sub(256, shl(3, length)) 11201 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11202 | | } 11203 | | m0 := mload(0x00) 11204 | | m1 := mload(0x20) 11205 | | m2 := mload(0x40) 11206 | | m3 := mload(0x60) 11207 | | m4 := mload(0x80) 11208 | | m5 := mload(0xa0) 11209 | | m6 := mload(0xc0) 11210 | | // Selector of `log(string,address,uint256,uint256)`. 11211 | | mstore(0x00, 0xf8f51b1e) 11212 | | mstore(0x20, 0x80) 11213 | | mstore(0x40, p1) 11214 | | mstore(0x60, p2) 11215 | | mstore(0x80, p3) 11216 | | writeString(0xa0, p0) 11217 | | } 11218 | | _sendLogPayload(0x1c, 0xc4); 11219 | | /// @solidity memory-safe-assembly 11220 | | assembly { 11221 | | mstore(0x00, m0) 11222 | | mstore(0x20, m1) 11223 | | mstore(0x40, m2) 11224 | | mstore(0x60, m3) 11225 | | mstore(0x80, m4) 11226 | | mstore(0xa0, m5) 11227 | | mstore(0xc0, m6) 11228 | | } 11229 | | } 11230 | | 11231 | | function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure { 11232 | | bytes32 m0; 11233 | | bytes32 m1; 11234 | | bytes32 m2; 11235 | | bytes32 m3; 11236 | | bytes32 m4; 11237 | | bytes32 m5; 11238 | | bytes32 m6; 11239 | | bytes32 m7; 11240 | | bytes32 m8; 11241 | | /// @solidity memory-safe-assembly 11242 | | assembly { 11243 | | function writeString(pos, w) { 11244 | | let length := 0 11245 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11246 | | mstore(pos, length) 11247 | | let shift := sub(256, shl(3, length)) 11248 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11249 | | } 11250 | | m0 := mload(0x00) 11251 | | m1 := mload(0x20) 11252 | | m2 := mload(0x40) 11253 | | m3 := mload(0x60) 11254 | | m4 := mload(0x80) 11255 | | m5 := mload(0xa0) 11256 | | m6 := mload(0xc0) 11257 | | m7 := mload(0xe0) 11258 | | m8 := mload(0x100) 11259 | | // Selector of `log(string,address,uint256,string)`. 11260 | | mstore(0x00, 0x5a477632) 11261 | | mstore(0x20, 0x80) 11262 | | mstore(0x40, p1) 11263 | | mstore(0x60, p2) 11264 | | mstore(0x80, 0xc0) 11265 | | writeString(0xa0, p0) 11266 | | writeString(0xe0, p3) 11267 | | } 11268 | | _sendLogPayload(0x1c, 0x104); 11269 | | /// @solidity memory-safe-assembly 11270 | | assembly { 11271 | | mstore(0x00, m0) 11272 | | mstore(0x20, m1) 11273 | | mstore(0x40, m2) 11274 | | mstore(0x60, m3) 11275 | | mstore(0x80, m4) 11276 | | mstore(0xa0, m5) 11277 | | mstore(0xc0, m6) 11278 | | mstore(0xe0, m7) 11279 | | mstore(0x100, m8) 11280 | | } 11281 | | } 11282 | | 11283 | | function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure { 11284 | | bytes32 m0; 11285 | | bytes32 m1; 11286 | | bytes32 m2; 11287 | | bytes32 m3; 11288 | | bytes32 m4; 11289 | | bytes32 m5; 11290 | | bytes32 m6; 11291 | | bytes32 m7; 11292 | | bytes32 m8; 11293 | | /// @solidity memory-safe-assembly 11294 | | assembly { 11295 | | function writeString(pos, w) { 11296 | | let length := 0 11297 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11298 | | mstore(pos, length) 11299 | | let shift := sub(256, shl(3, length)) 11300 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11301 | | } 11302 | | m0 := mload(0x00) 11303 | | m1 := mload(0x20) 11304 | | m2 := mload(0x40) 11305 | | m3 := mload(0x60) 11306 | | m4 := mload(0x80) 11307 | | m5 := mload(0xa0) 11308 | | m6 := mload(0xc0) 11309 | | m7 := mload(0xe0) 11310 | | m8 := mload(0x100) 11311 | | // Selector of `log(string,address,string,address)`. 11312 | | mstore(0x00, 0xaabc9a31) 11313 | | mstore(0x20, 0x80) 11314 | | mstore(0x40, p1) 11315 | | mstore(0x60, 0xc0) 11316 | | mstore(0x80, p3) 11317 | | writeString(0xa0, p0) 11318 | | writeString(0xe0, p2) 11319 | | } 11320 | | _sendLogPayload(0x1c, 0x104); 11321 | | /// @solidity memory-safe-assembly 11322 | | assembly { 11323 | | mstore(0x00, m0) 11324 | | mstore(0x20, m1) 11325 | | mstore(0x40, m2) 11326 | | mstore(0x60, m3) 11327 | | mstore(0x80, m4) 11328 | | mstore(0xa0, m5) 11329 | | mstore(0xc0, m6) 11330 | | mstore(0xe0, m7) 11331 | | mstore(0x100, m8) 11332 | | } 11333 | | } 11334 | | 11335 | | function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure { 11336 | | bytes32 m0; 11337 | | bytes32 m1; 11338 | | bytes32 m2; 11339 | | bytes32 m3; 11340 | | bytes32 m4; 11341 | | bytes32 m5; 11342 | | bytes32 m6; 11343 | | bytes32 m7; 11344 | | bytes32 m8; 11345 | | /// @solidity memory-safe-assembly 11346 | | assembly { 11347 | | function writeString(pos, w) { 11348 | | let length := 0 11349 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11350 | | mstore(pos, length) 11351 | | let shift := sub(256, shl(3, length)) 11352 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11353 | | } 11354 | | m0 := mload(0x00) 11355 | | m1 := mload(0x20) 11356 | | m2 := mload(0x40) 11357 | | m3 := mload(0x60) 11358 | | m4 := mload(0x80) 11359 | | m5 := mload(0xa0) 11360 | | m6 := mload(0xc0) 11361 | | m7 := mload(0xe0) 11362 | | m8 := mload(0x100) 11363 | | // Selector of `log(string,address,string,bool)`. 11364 | | mstore(0x00, 0x5f15d28c) 11365 | | mstore(0x20, 0x80) 11366 | | mstore(0x40, p1) 11367 | | mstore(0x60, 0xc0) 11368 | | mstore(0x80, p3) 11369 | | writeString(0xa0, p0) 11370 | | writeString(0xe0, p2) 11371 | | } 11372 | | _sendLogPayload(0x1c, 0x104); 11373 | | /// @solidity memory-safe-assembly 11374 | | assembly { 11375 | | mstore(0x00, m0) 11376 | | mstore(0x20, m1) 11377 | | mstore(0x40, m2) 11378 | | mstore(0x60, m3) 11379 | | mstore(0x80, m4) 11380 | | mstore(0xa0, m5) 11381 | | mstore(0xc0, m6) 11382 | | mstore(0xe0, m7) 11383 | | mstore(0x100, m8) 11384 | | } 11385 | | } 11386 | | 11387 | | function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure { 11388 | | bytes32 m0; 11389 | | bytes32 m1; 11390 | | bytes32 m2; 11391 | | bytes32 m3; 11392 | | bytes32 m4; 11393 | | bytes32 m5; 11394 | | bytes32 m6; 11395 | | bytes32 m7; 11396 | | bytes32 m8; 11397 | | /// @solidity memory-safe-assembly 11398 | | assembly { 11399 | | function writeString(pos, w) { 11400 | | let length := 0 11401 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11402 | | mstore(pos, length) 11403 | | let shift := sub(256, shl(3, length)) 11404 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11405 | | } 11406 | | m0 := mload(0x00) 11407 | | m1 := mload(0x20) 11408 | | m2 := mload(0x40) 11409 | | m3 := mload(0x60) 11410 | | m4 := mload(0x80) 11411 | | m5 := mload(0xa0) 11412 | | m6 := mload(0xc0) 11413 | | m7 := mload(0xe0) 11414 | | m8 := mload(0x100) 11415 | | // Selector of `log(string,address,string,uint256)`. 11416 | | mstore(0x00, 0x91d1112e) 11417 | | mstore(0x20, 0x80) 11418 | | mstore(0x40, p1) 11419 | | mstore(0x60, 0xc0) 11420 | | mstore(0x80, p3) 11421 | | writeString(0xa0, p0) 11422 | | writeString(0xe0, p2) 11423 | | } 11424 | | _sendLogPayload(0x1c, 0x104); 11425 | | /// @solidity memory-safe-assembly 11426 | | assembly { 11427 | | mstore(0x00, m0) 11428 | | mstore(0x20, m1) 11429 | | mstore(0x40, m2) 11430 | | mstore(0x60, m3) 11431 | | mstore(0x80, m4) 11432 | | mstore(0xa0, m5) 11433 | | mstore(0xc0, m6) 11434 | | mstore(0xe0, m7) 11435 | | mstore(0x100, m8) 11436 | | } 11437 | | } 11438 | | 11439 | | function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure { 11440 | | bytes32 m0; 11441 | | bytes32 m1; 11442 | | bytes32 m2; 11443 | | bytes32 m3; 11444 | | bytes32 m4; 11445 | | bytes32 m5; 11446 | | bytes32 m6; 11447 | | bytes32 m7; 11448 | | bytes32 m8; 11449 | | bytes32 m9; 11450 | | bytes32 m10; 11451 | | /// @solidity memory-safe-assembly 11452 | | assembly { 11453 | | function writeString(pos, w) { 11454 | | let length := 0 11455 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11456 | | mstore(pos, length) 11457 | | let shift := sub(256, shl(3, length)) 11458 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11459 | | } 11460 | | m0 := mload(0x00) 11461 | | m1 := mload(0x20) 11462 | | m2 := mload(0x40) 11463 | | m3 := mload(0x60) 11464 | | m4 := mload(0x80) 11465 | | m5 := mload(0xa0) 11466 | | m6 := mload(0xc0) 11467 | | m7 := mload(0xe0) 11468 | | m8 := mload(0x100) 11469 | | m9 := mload(0x120) 11470 | | m10 := mload(0x140) 11471 | | // Selector of `log(string,address,string,string)`. 11472 | | mstore(0x00, 0x245986f2) 11473 | | mstore(0x20, 0x80) 11474 | | mstore(0x40, p1) 11475 | | mstore(0x60, 0xc0) 11476 | | mstore(0x80, 0x100) 11477 | | writeString(0xa0, p0) 11478 | | writeString(0xe0, p2) 11479 | | writeString(0x120, p3) 11480 | | } 11481 | | _sendLogPayload(0x1c, 0x144); 11482 | | /// @solidity memory-safe-assembly 11483 | | assembly { 11484 | | mstore(0x00, m0) 11485 | | mstore(0x20, m1) 11486 | | mstore(0x40, m2) 11487 | | mstore(0x60, m3) 11488 | | mstore(0x80, m4) 11489 | | mstore(0xa0, m5) 11490 | | mstore(0xc0, m6) 11491 | | mstore(0xe0, m7) 11492 | | mstore(0x100, m8) 11493 | | mstore(0x120, m9) 11494 | | mstore(0x140, m10) 11495 | | } 11496 | | } 11497 | | 11498 | | function log(bytes32 p0, bool p1, address p2, address p3) internal pure { 11499 | | bytes32 m0; 11500 | | bytes32 m1; 11501 | | bytes32 m2; 11502 | | bytes32 m3; 11503 | | bytes32 m4; 11504 | | bytes32 m5; 11505 | | bytes32 m6; 11506 | | /// @solidity memory-safe-assembly 11507 | | assembly { 11508 | | function writeString(pos, w) { 11509 | | let length := 0 11510 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11511 | | mstore(pos, length) 11512 | | let shift := sub(256, shl(3, length)) 11513 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11514 | | } 11515 | | m0 := mload(0x00) 11516 | | m1 := mload(0x20) 11517 | | m2 := mload(0x40) 11518 | | m3 := mload(0x60) 11519 | | m4 := mload(0x80) 11520 | | m5 := mload(0xa0) 11521 | | m6 := mload(0xc0) 11522 | | // Selector of `log(string,bool,address,address)`. 11523 | | mstore(0x00, 0x33e9dd1d) 11524 | | mstore(0x20, 0x80) 11525 | | mstore(0x40, p1) 11526 | | mstore(0x60, p2) 11527 | | mstore(0x80, p3) 11528 | | writeString(0xa0, p0) 11529 | | } 11530 | | _sendLogPayload(0x1c, 0xc4); 11531 | | /// @solidity memory-safe-assembly 11532 | | assembly { 11533 | | mstore(0x00, m0) 11534 | | mstore(0x20, m1) 11535 | | mstore(0x40, m2) 11536 | | mstore(0x60, m3) 11537 | | mstore(0x80, m4) 11538 | | mstore(0xa0, m5) 11539 | | mstore(0xc0, m6) 11540 | | } 11541 | | } 11542 | | 11543 | | function log(bytes32 p0, bool p1, address p2, bool p3) internal pure { 11544 | | bytes32 m0; 11545 | | bytes32 m1; 11546 | | bytes32 m2; 11547 | | bytes32 m3; 11548 | | bytes32 m4; 11549 | | bytes32 m5; 11550 | | bytes32 m6; 11551 | | /// @solidity memory-safe-assembly 11552 | | assembly { 11553 | | function writeString(pos, w) { 11554 | | let length := 0 11555 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11556 | | mstore(pos, length) 11557 | | let shift := sub(256, shl(3, length)) 11558 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11559 | | } 11560 | | m0 := mload(0x00) 11561 | | m1 := mload(0x20) 11562 | | m2 := mload(0x40) 11563 | | m3 := mload(0x60) 11564 | | m4 := mload(0x80) 11565 | | m5 := mload(0xa0) 11566 | | m6 := mload(0xc0) 11567 | | // Selector of `log(string,bool,address,bool)`. 11568 | | mstore(0x00, 0x958c28c6) 11569 | | mstore(0x20, 0x80) 11570 | | mstore(0x40, p1) 11571 | | mstore(0x60, p2) 11572 | | mstore(0x80, p3) 11573 | | writeString(0xa0, p0) 11574 | | } 11575 | | _sendLogPayload(0x1c, 0xc4); 11576 | | /// @solidity memory-safe-assembly 11577 | | assembly { 11578 | | mstore(0x00, m0) 11579 | | mstore(0x20, m1) 11580 | | mstore(0x40, m2) 11581 | | mstore(0x60, m3) 11582 | | mstore(0x80, m4) 11583 | | mstore(0xa0, m5) 11584 | | mstore(0xc0, m6) 11585 | | } 11586 | | } 11587 | | 11588 | | function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure { 11589 | | bytes32 m0; 11590 | | bytes32 m1; 11591 | | bytes32 m2; 11592 | | bytes32 m3; 11593 | | bytes32 m4; 11594 | | bytes32 m5; 11595 | | bytes32 m6; 11596 | | /// @solidity memory-safe-assembly 11597 | | assembly { 11598 | | function writeString(pos, w) { 11599 | | let length := 0 11600 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11601 | | mstore(pos, length) 11602 | | let shift := sub(256, shl(3, length)) 11603 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11604 | | } 11605 | | m0 := mload(0x00) 11606 | | m1 := mload(0x20) 11607 | | m2 := mload(0x40) 11608 | | m3 := mload(0x60) 11609 | | m4 := mload(0x80) 11610 | | m5 := mload(0xa0) 11611 | | m6 := mload(0xc0) 11612 | | // Selector of `log(string,bool,address,uint256)`. 11613 | | mstore(0x00, 0x5d08bb05) 11614 | | mstore(0x20, 0x80) 11615 | | mstore(0x40, p1) 11616 | | mstore(0x60, p2) 11617 | | mstore(0x80, p3) 11618 | | writeString(0xa0, p0) 11619 | | } 11620 | | _sendLogPayload(0x1c, 0xc4); 11621 | | /// @solidity memory-safe-assembly 11622 | | assembly { 11623 | | mstore(0x00, m0) 11624 | | mstore(0x20, m1) 11625 | | mstore(0x40, m2) 11626 | | mstore(0x60, m3) 11627 | | mstore(0x80, m4) 11628 | | mstore(0xa0, m5) 11629 | | mstore(0xc0, m6) 11630 | | } 11631 | | } 11632 | | 11633 | | function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure { 11634 | | bytes32 m0; 11635 | | bytes32 m1; 11636 | | bytes32 m2; 11637 | | bytes32 m3; 11638 | | bytes32 m4; 11639 | | bytes32 m5; 11640 | | bytes32 m6; 11641 | | bytes32 m7; 11642 | | bytes32 m8; 11643 | | /// @solidity memory-safe-assembly 11644 | | assembly { 11645 | | function writeString(pos, w) { 11646 | | let length := 0 11647 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11648 | | mstore(pos, length) 11649 | | let shift := sub(256, shl(3, length)) 11650 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11651 | | } 11652 | | m0 := mload(0x00) 11653 | | m1 := mload(0x20) 11654 | | m2 := mload(0x40) 11655 | | m3 := mload(0x60) 11656 | | m4 := mload(0x80) 11657 | | m5 := mload(0xa0) 11658 | | m6 := mload(0xc0) 11659 | | m7 := mload(0xe0) 11660 | | m8 := mload(0x100) 11661 | | // Selector of `log(string,bool,address,string)`. 11662 | | mstore(0x00, 0x2d8e33a4) 11663 | | mstore(0x20, 0x80) 11664 | | mstore(0x40, p1) 11665 | | mstore(0x60, p2) 11666 | | mstore(0x80, 0xc0) 11667 | | writeString(0xa0, p0) 11668 | | writeString(0xe0, p3) 11669 | | } 11670 | | _sendLogPayload(0x1c, 0x104); 11671 | | /// @solidity memory-safe-assembly 11672 | | assembly { 11673 | | mstore(0x00, m0) 11674 | | mstore(0x20, m1) 11675 | | mstore(0x40, m2) 11676 | | mstore(0x60, m3) 11677 | | mstore(0x80, m4) 11678 | | mstore(0xa0, m5) 11679 | | mstore(0xc0, m6) 11680 | | mstore(0xe0, m7) 11681 | | mstore(0x100, m8) 11682 | | } 11683 | | } 11684 | | 11685 | | function log(bytes32 p0, bool p1, bool p2, address p3) internal pure { 11686 | | bytes32 m0; 11687 | | bytes32 m1; 11688 | | bytes32 m2; 11689 | | bytes32 m3; 11690 | | bytes32 m4; 11691 | | bytes32 m5; 11692 | | bytes32 m6; 11693 | | /// @solidity memory-safe-assembly 11694 | | assembly { 11695 | | function writeString(pos, w) { 11696 | | let length := 0 11697 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11698 | | mstore(pos, length) 11699 | | let shift := sub(256, shl(3, length)) 11700 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11701 | | } 11702 | | m0 := mload(0x00) 11703 | | m1 := mload(0x20) 11704 | | m2 := mload(0x40) 11705 | | m3 := mload(0x60) 11706 | | m4 := mload(0x80) 11707 | | m5 := mload(0xa0) 11708 | | m6 := mload(0xc0) 11709 | | // Selector of `log(string,bool,bool,address)`. 11710 | | mstore(0x00, 0x7190a529) 11711 | | mstore(0x20, 0x80) 11712 | | mstore(0x40, p1) 11713 | | mstore(0x60, p2) 11714 | | mstore(0x80, p3) 11715 | | writeString(0xa0, p0) 11716 | | } 11717 | | _sendLogPayload(0x1c, 0xc4); 11718 | | /// @solidity memory-safe-assembly 11719 | | assembly { 11720 | | mstore(0x00, m0) 11721 | | mstore(0x20, m1) 11722 | | mstore(0x40, m2) 11723 | | mstore(0x60, m3) 11724 | | mstore(0x80, m4) 11725 | | mstore(0xa0, m5) 11726 | | mstore(0xc0, m6) 11727 | | } 11728 | | } 11729 | | 11730 | | function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure { 11731 | | bytes32 m0; 11732 | | bytes32 m1; 11733 | | bytes32 m2; 11734 | | bytes32 m3; 11735 | | bytes32 m4; 11736 | | bytes32 m5; 11737 | | bytes32 m6; 11738 | | /// @solidity memory-safe-assembly 11739 | | assembly { 11740 | | function writeString(pos, w) { 11741 | | let length := 0 11742 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11743 | | mstore(pos, length) 11744 | | let shift := sub(256, shl(3, length)) 11745 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11746 | | } 11747 | | m0 := mload(0x00) 11748 | | m1 := mload(0x20) 11749 | | m2 := mload(0x40) 11750 | | m3 := mload(0x60) 11751 | | m4 := mload(0x80) 11752 | | m5 := mload(0xa0) 11753 | | m6 := mload(0xc0) 11754 | | // Selector of `log(string,bool,bool,bool)`. 11755 | | mstore(0x00, 0x895af8c5) 11756 | | mstore(0x20, 0x80) 11757 | | mstore(0x40, p1) 11758 | | mstore(0x60, p2) 11759 | | mstore(0x80, p3) 11760 | | writeString(0xa0, p0) 11761 | | } 11762 | | _sendLogPayload(0x1c, 0xc4); 11763 | | /// @solidity memory-safe-assembly 11764 | | assembly { 11765 | | mstore(0x00, m0) 11766 | | mstore(0x20, m1) 11767 | | mstore(0x40, m2) 11768 | | mstore(0x60, m3) 11769 | | mstore(0x80, m4) 11770 | | mstore(0xa0, m5) 11771 | | mstore(0xc0, m6) 11772 | | } 11773 | | } 11774 | | 11775 | | function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure { 11776 | | bytes32 m0; 11777 | | bytes32 m1; 11778 | | bytes32 m2; 11779 | | bytes32 m3; 11780 | | bytes32 m4; 11781 | | bytes32 m5; 11782 | | bytes32 m6; 11783 | | /// @solidity memory-safe-assembly 11784 | | assembly { 11785 | | function writeString(pos, w) { 11786 | | let length := 0 11787 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11788 | | mstore(pos, length) 11789 | | let shift := sub(256, shl(3, length)) 11790 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11791 | | } 11792 | | m0 := mload(0x00) 11793 | | m1 := mload(0x20) 11794 | | m2 := mload(0x40) 11795 | | m3 := mload(0x60) 11796 | | m4 := mload(0x80) 11797 | | m5 := mload(0xa0) 11798 | | m6 := mload(0xc0) 11799 | | // Selector of `log(string,bool,bool,uint256)`. 11800 | | mstore(0x00, 0x8e3f78a9) 11801 | | mstore(0x20, 0x80) 11802 | | mstore(0x40, p1) 11803 | | mstore(0x60, p2) 11804 | | mstore(0x80, p3) 11805 | | writeString(0xa0, p0) 11806 | | } 11807 | | _sendLogPayload(0x1c, 0xc4); 11808 | | /// @solidity memory-safe-assembly 11809 | | assembly { 11810 | | mstore(0x00, m0) 11811 | | mstore(0x20, m1) 11812 | | mstore(0x40, m2) 11813 | | mstore(0x60, m3) 11814 | | mstore(0x80, m4) 11815 | | mstore(0xa0, m5) 11816 | | mstore(0xc0, m6) 11817 | | } 11818 | | } 11819 | | 11820 | | function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure { 11821 | | bytes32 m0; 11822 | | bytes32 m1; 11823 | | bytes32 m2; 11824 | | bytes32 m3; 11825 | | bytes32 m4; 11826 | | bytes32 m5; 11827 | | bytes32 m6; 11828 | | bytes32 m7; 11829 | | bytes32 m8; 11830 | | /// @solidity memory-safe-assembly 11831 | | assembly { 11832 | | function writeString(pos, w) { 11833 | | let length := 0 11834 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11835 | | mstore(pos, length) 11836 | | let shift := sub(256, shl(3, length)) 11837 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11838 | | } 11839 | | m0 := mload(0x00) 11840 | | m1 := mload(0x20) 11841 | | m2 := mload(0x40) 11842 | | m3 := mload(0x60) 11843 | | m4 := mload(0x80) 11844 | | m5 := mload(0xa0) 11845 | | m6 := mload(0xc0) 11846 | | m7 := mload(0xe0) 11847 | | m8 := mload(0x100) 11848 | | // Selector of `log(string,bool,bool,string)`. 11849 | | mstore(0x00, 0x9d22d5dd) 11850 | | mstore(0x20, 0x80) 11851 | | mstore(0x40, p1) 11852 | | mstore(0x60, p2) 11853 | | mstore(0x80, 0xc0) 11854 | | writeString(0xa0, p0) 11855 | | writeString(0xe0, p3) 11856 | | } 11857 | | _sendLogPayload(0x1c, 0x104); 11858 | | /// @solidity memory-safe-assembly 11859 | | assembly { 11860 | | mstore(0x00, m0) 11861 | | mstore(0x20, m1) 11862 | | mstore(0x40, m2) 11863 | | mstore(0x60, m3) 11864 | | mstore(0x80, m4) 11865 | | mstore(0xa0, m5) 11866 | | mstore(0xc0, m6) 11867 | | mstore(0xe0, m7) 11868 | | mstore(0x100, m8) 11869 | | } 11870 | | } 11871 | | 11872 | | function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure { 11873 | | bytes32 m0; 11874 | | bytes32 m1; 11875 | | bytes32 m2; 11876 | | bytes32 m3; 11877 | | bytes32 m4; 11878 | | bytes32 m5; 11879 | | bytes32 m6; 11880 | | /// @solidity memory-safe-assembly 11881 | | assembly { 11882 | | function writeString(pos, w) { 11883 | | let length := 0 11884 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11885 | | mstore(pos, length) 11886 | | let shift := sub(256, shl(3, length)) 11887 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11888 | | } 11889 | | m0 := mload(0x00) 11890 | | m1 := mload(0x20) 11891 | | m2 := mload(0x40) 11892 | | m3 := mload(0x60) 11893 | | m4 := mload(0x80) 11894 | | m5 := mload(0xa0) 11895 | | m6 := mload(0xc0) 11896 | | // Selector of `log(string,bool,uint256,address)`. 11897 | | mstore(0x00, 0x935e09bf) 11898 | | mstore(0x20, 0x80) 11899 | | mstore(0x40, p1) 11900 | | mstore(0x60, p2) 11901 | | mstore(0x80, p3) 11902 | | writeString(0xa0, p0) 11903 | | } 11904 | | _sendLogPayload(0x1c, 0xc4); 11905 | | /// @solidity memory-safe-assembly 11906 | | assembly { 11907 | | mstore(0x00, m0) 11908 | | mstore(0x20, m1) 11909 | | mstore(0x40, m2) 11910 | | mstore(0x60, m3) 11911 | | mstore(0x80, m4) 11912 | | mstore(0xa0, m5) 11913 | | mstore(0xc0, m6) 11914 | | } 11915 | | } 11916 | | 11917 | | function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure { 11918 | | bytes32 m0; 11919 | | bytes32 m1; 11920 | | bytes32 m2; 11921 | | bytes32 m3; 11922 | | bytes32 m4; 11923 | | bytes32 m5; 11924 | | bytes32 m6; 11925 | | /// @solidity memory-safe-assembly 11926 | | assembly { 11927 | | function writeString(pos, w) { 11928 | | let length := 0 11929 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11930 | | mstore(pos, length) 11931 | | let shift := sub(256, shl(3, length)) 11932 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11933 | | } 11934 | | m0 := mload(0x00) 11935 | | m1 := mload(0x20) 11936 | | m2 := mload(0x40) 11937 | | m3 := mload(0x60) 11938 | | m4 := mload(0x80) 11939 | | m5 := mload(0xa0) 11940 | | m6 := mload(0xc0) 11941 | | // Selector of `log(string,bool,uint256,bool)`. 11942 | | mstore(0x00, 0x8af7cf8a) 11943 | | mstore(0x20, 0x80) 11944 | | mstore(0x40, p1) 11945 | | mstore(0x60, p2) 11946 | | mstore(0x80, p3) 11947 | | writeString(0xa0, p0) 11948 | | } 11949 | | _sendLogPayload(0x1c, 0xc4); 11950 | | /// @solidity memory-safe-assembly 11951 | | assembly { 11952 | | mstore(0x00, m0) 11953 | | mstore(0x20, m1) 11954 | | mstore(0x40, m2) 11955 | | mstore(0x60, m3) 11956 | | mstore(0x80, m4) 11957 | | mstore(0xa0, m5) 11958 | | mstore(0xc0, m6) 11959 | | } 11960 | | } 11961 | | 11962 | | function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure { 11963 | | bytes32 m0; 11964 | | bytes32 m1; 11965 | | bytes32 m2; 11966 | | bytes32 m3; 11967 | | bytes32 m4; 11968 | | bytes32 m5; 11969 | | bytes32 m6; 11970 | | /// @solidity memory-safe-assembly 11971 | | assembly { 11972 | | function writeString(pos, w) { 11973 | | let length := 0 11974 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 11975 | | mstore(pos, length) 11976 | | let shift := sub(256, shl(3, length)) 11977 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 11978 | | } 11979 | | m0 := mload(0x00) 11980 | | m1 := mload(0x20) 11981 | | m2 := mload(0x40) 11982 | | m3 := mload(0x60) 11983 | | m4 := mload(0x80) 11984 | | m5 := mload(0xa0) 11985 | | m6 := mload(0xc0) 11986 | | // Selector of `log(string,bool,uint256,uint256)`. 11987 | | mstore(0x00, 0x64b5bb67) 11988 | | mstore(0x20, 0x80) 11989 | | mstore(0x40, p1) 11990 | | mstore(0x60, p2) 11991 | | mstore(0x80, p3) 11992 | | writeString(0xa0, p0) 11993 | | } 11994 | | _sendLogPayload(0x1c, 0xc4); 11995 | | /// @solidity memory-safe-assembly 11996 | | assembly { 11997 | | mstore(0x00, m0) 11998 | | mstore(0x20, m1) 11999 | | mstore(0x40, m2) 12000 | | mstore(0x60, m3) 12001 | | mstore(0x80, m4) 12002 | | mstore(0xa0, m5) 12003 | | mstore(0xc0, m6) 12004 | | } 12005 | | } 12006 | | 12007 | | function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure { 12008 | | bytes32 m0; 12009 | | bytes32 m1; 12010 | | bytes32 m2; 12011 | | bytes32 m3; 12012 | | bytes32 m4; 12013 | | bytes32 m5; 12014 | | bytes32 m6; 12015 | | bytes32 m7; 12016 | | bytes32 m8; 12017 | | /// @solidity memory-safe-assembly 12018 | | assembly { 12019 | | function writeString(pos, w) { 12020 | | let length := 0 12021 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12022 | | mstore(pos, length) 12023 | | let shift := sub(256, shl(3, length)) 12024 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12025 | | } 12026 | | m0 := mload(0x00) 12027 | | m1 := mload(0x20) 12028 | | m2 := mload(0x40) 12029 | | m3 := mload(0x60) 12030 | | m4 := mload(0x80) 12031 | | m5 := mload(0xa0) 12032 | | m6 := mload(0xc0) 12033 | | m7 := mload(0xe0) 12034 | | m8 := mload(0x100) 12035 | | // Selector of `log(string,bool,uint256,string)`. 12036 | | mstore(0x00, 0x742d6ee7) 12037 | | mstore(0x20, 0x80) 12038 | | mstore(0x40, p1) 12039 | | mstore(0x60, p2) 12040 | | mstore(0x80, 0xc0) 12041 | | writeString(0xa0, p0) 12042 | | writeString(0xe0, p3) 12043 | | } 12044 | | _sendLogPayload(0x1c, 0x104); 12045 | | /// @solidity memory-safe-assembly 12046 | | assembly { 12047 | | mstore(0x00, m0) 12048 | | mstore(0x20, m1) 12049 | | mstore(0x40, m2) 12050 | | mstore(0x60, m3) 12051 | | mstore(0x80, m4) 12052 | | mstore(0xa0, m5) 12053 | | mstore(0xc0, m6) 12054 | | mstore(0xe0, m7) 12055 | | mstore(0x100, m8) 12056 | | } 12057 | | } 12058 | | 12059 | | function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure { 12060 | | bytes32 m0; 12061 | | bytes32 m1; 12062 | | bytes32 m2; 12063 | | bytes32 m3; 12064 | | bytes32 m4; 12065 | | bytes32 m5; 12066 | | bytes32 m6; 12067 | | bytes32 m7; 12068 | | bytes32 m8; 12069 | | /// @solidity memory-safe-assembly 12070 | | assembly { 12071 | | function writeString(pos, w) { 12072 | | let length := 0 12073 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12074 | | mstore(pos, length) 12075 | | let shift := sub(256, shl(3, length)) 12076 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12077 | | } 12078 | | m0 := mload(0x00) 12079 | | m1 := mload(0x20) 12080 | | m2 := mload(0x40) 12081 | | m3 := mload(0x60) 12082 | | m4 := mload(0x80) 12083 | | m5 := mload(0xa0) 12084 | | m6 := mload(0xc0) 12085 | | m7 := mload(0xe0) 12086 | | m8 := mload(0x100) 12087 | | // Selector of `log(string,bool,string,address)`. 12088 | | mstore(0x00, 0xe0625b29) 12089 | | mstore(0x20, 0x80) 12090 | | mstore(0x40, p1) 12091 | | mstore(0x60, 0xc0) 12092 | | mstore(0x80, p3) 12093 | | writeString(0xa0, p0) 12094 | | writeString(0xe0, p2) 12095 | | } 12096 | | _sendLogPayload(0x1c, 0x104); 12097 | | /// @solidity memory-safe-assembly 12098 | | assembly { 12099 | | mstore(0x00, m0) 12100 | | mstore(0x20, m1) 12101 | | mstore(0x40, m2) 12102 | | mstore(0x60, m3) 12103 | | mstore(0x80, m4) 12104 | | mstore(0xa0, m5) 12105 | | mstore(0xc0, m6) 12106 | | mstore(0xe0, m7) 12107 | | mstore(0x100, m8) 12108 | | } 12109 | | } 12110 | | 12111 | | function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure { 12112 | | bytes32 m0; 12113 | | bytes32 m1; 12114 | | bytes32 m2; 12115 | | bytes32 m3; 12116 | | bytes32 m4; 12117 | | bytes32 m5; 12118 | | bytes32 m6; 12119 | | bytes32 m7; 12120 | | bytes32 m8; 12121 | | /// @solidity memory-safe-assembly 12122 | | assembly { 12123 | | function writeString(pos, w) { 12124 | | let length := 0 12125 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12126 | | mstore(pos, length) 12127 | | let shift := sub(256, shl(3, length)) 12128 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12129 | | } 12130 | | m0 := mload(0x00) 12131 | | m1 := mload(0x20) 12132 | | m2 := mload(0x40) 12133 | | m3 := mload(0x60) 12134 | | m4 := mload(0x80) 12135 | | m5 := mload(0xa0) 12136 | | m6 := mload(0xc0) 12137 | | m7 := mload(0xe0) 12138 | | m8 := mload(0x100) 12139 | | // Selector of `log(string,bool,string,bool)`. 12140 | | mstore(0x00, 0x3f8a701d) 12141 | | mstore(0x20, 0x80) 12142 | | mstore(0x40, p1) 12143 | | mstore(0x60, 0xc0) 12144 | | mstore(0x80, p3) 12145 | | writeString(0xa0, p0) 12146 | | writeString(0xe0, p2) 12147 | | } 12148 | | _sendLogPayload(0x1c, 0x104); 12149 | | /// @solidity memory-safe-assembly 12150 | | assembly { 12151 | | mstore(0x00, m0) 12152 | | mstore(0x20, m1) 12153 | | mstore(0x40, m2) 12154 | | mstore(0x60, m3) 12155 | | mstore(0x80, m4) 12156 | | mstore(0xa0, m5) 12157 | | mstore(0xc0, m6) 12158 | | mstore(0xe0, m7) 12159 | | mstore(0x100, m8) 12160 | | } 12161 | | } 12162 | | 12163 | | function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure { 12164 | | bytes32 m0; 12165 | | bytes32 m1; 12166 | | bytes32 m2; 12167 | | bytes32 m3; 12168 | | bytes32 m4; 12169 | | bytes32 m5; 12170 | | bytes32 m6; 12171 | | bytes32 m7; 12172 | | bytes32 m8; 12173 | | /// @solidity memory-safe-assembly 12174 | | assembly { 12175 | | function writeString(pos, w) { 12176 | | let length := 0 12177 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12178 | | mstore(pos, length) 12179 | | let shift := sub(256, shl(3, length)) 12180 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12181 | | } 12182 | | m0 := mload(0x00) 12183 | | m1 := mload(0x20) 12184 | | m2 := mload(0x40) 12185 | | m3 := mload(0x60) 12186 | | m4 := mload(0x80) 12187 | | m5 := mload(0xa0) 12188 | | m6 := mload(0xc0) 12189 | | m7 := mload(0xe0) 12190 | | m8 := mload(0x100) 12191 | | // Selector of `log(string,bool,string,uint256)`. 12192 | | mstore(0x00, 0x24f91465) 12193 | | mstore(0x20, 0x80) 12194 | | mstore(0x40, p1) 12195 | | mstore(0x60, 0xc0) 12196 | | mstore(0x80, p3) 12197 | | writeString(0xa0, p0) 12198 | | writeString(0xe0, p2) 12199 | | } 12200 | | _sendLogPayload(0x1c, 0x104); 12201 | | /// @solidity memory-safe-assembly 12202 | | assembly { 12203 | | mstore(0x00, m0) 12204 | | mstore(0x20, m1) 12205 | | mstore(0x40, m2) 12206 | | mstore(0x60, m3) 12207 | | mstore(0x80, m4) 12208 | | mstore(0xa0, m5) 12209 | | mstore(0xc0, m6) 12210 | | mstore(0xe0, m7) 12211 | | mstore(0x100, m8) 12212 | | } 12213 | | } 12214 | | 12215 | | function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure { 12216 | | bytes32 m0; 12217 | | bytes32 m1; 12218 | | bytes32 m2; 12219 | | bytes32 m3; 12220 | | bytes32 m4; 12221 | | bytes32 m5; 12222 | | bytes32 m6; 12223 | | bytes32 m7; 12224 | | bytes32 m8; 12225 | | bytes32 m9; 12226 | | bytes32 m10; 12227 | | /// @solidity memory-safe-assembly 12228 | | assembly { 12229 | | function writeString(pos, w) { 12230 | | let length := 0 12231 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12232 | | mstore(pos, length) 12233 | | let shift := sub(256, shl(3, length)) 12234 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12235 | | } 12236 | | m0 := mload(0x00) 12237 | | m1 := mload(0x20) 12238 | | m2 := mload(0x40) 12239 | | m3 := mload(0x60) 12240 | | m4 := mload(0x80) 12241 | | m5 := mload(0xa0) 12242 | | m6 := mload(0xc0) 12243 | | m7 := mload(0xe0) 12244 | | m8 := mload(0x100) 12245 | | m9 := mload(0x120) 12246 | | m10 := mload(0x140) 12247 | | // Selector of `log(string,bool,string,string)`. 12248 | | mstore(0x00, 0xa826caeb) 12249 | | mstore(0x20, 0x80) 12250 | | mstore(0x40, p1) 12251 | | mstore(0x60, 0xc0) 12252 | | mstore(0x80, 0x100) 12253 | | writeString(0xa0, p0) 12254 | | writeString(0xe0, p2) 12255 | | writeString(0x120, p3) 12256 | | } 12257 | | _sendLogPayload(0x1c, 0x144); 12258 | | /// @solidity memory-safe-assembly 12259 | | assembly { 12260 | | mstore(0x00, m0) 12261 | | mstore(0x20, m1) 12262 | | mstore(0x40, m2) 12263 | | mstore(0x60, m3) 12264 | | mstore(0x80, m4) 12265 | | mstore(0xa0, m5) 12266 | | mstore(0xc0, m6) 12267 | | mstore(0xe0, m7) 12268 | | mstore(0x100, m8) 12269 | | mstore(0x120, m9) 12270 | | mstore(0x140, m10) 12271 | | } 12272 | | } 12273 | | 12274 | | function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure { 12275 | | bytes32 m0; 12276 | | bytes32 m1; 12277 | | bytes32 m2; 12278 | | bytes32 m3; 12279 | | bytes32 m4; 12280 | | bytes32 m5; 12281 | | bytes32 m6; 12282 | | /// @solidity memory-safe-assembly 12283 | | assembly { 12284 | | function writeString(pos, w) { 12285 | | let length := 0 12286 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12287 | | mstore(pos, length) 12288 | | let shift := sub(256, shl(3, length)) 12289 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12290 | | } 12291 | | m0 := mload(0x00) 12292 | | m1 := mload(0x20) 12293 | | m2 := mload(0x40) 12294 | | m3 := mload(0x60) 12295 | | m4 := mload(0x80) 12296 | | m5 := mload(0xa0) 12297 | | m6 := mload(0xc0) 12298 | | // Selector of `log(string,uint256,address,address)`. 12299 | | mstore(0x00, 0x5ea2b7ae) 12300 | | mstore(0x20, 0x80) 12301 | | mstore(0x40, p1) 12302 | | mstore(0x60, p2) 12303 | | mstore(0x80, p3) 12304 | | writeString(0xa0, p0) 12305 | | } 12306 | | _sendLogPayload(0x1c, 0xc4); 12307 | | /// @solidity memory-safe-assembly 12308 | | assembly { 12309 | | mstore(0x00, m0) 12310 | | mstore(0x20, m1) 12311 | | mstore(0x40, m2) 12312 | | mstore(0x60, m3) 12313 | | mstore(0x80, m4) 12314 | | mstore(0xa0, m5) 12315 | | mstore(0xc0, m6) 12316 | | } 12317 | | } 12318 | | 12319 | | function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure { 12320 | | bytes32 m0; 12321 | | bytes32 m1; 12322 | | bytes32 m2; 12323 | | bytes32 m3; 12324 | | bytes32 m4; 12325 | | bytes32 m5; 12326 | | bytes32 m6; 12327 | | /// @solidity memory-safe-assembly 12328 | | assembly { 12329 | | function writeString(pos, w) { 12330 | | let length := 0 12331 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12332 | | mstore(pos, length) 12333 | | let shift := sub(256, shl(3, length)) 12334 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12335 | | } 12336 | | m0 := mload(0x00) 12337 | | m1 := mload(0x20) 12338 | | m2 := mload(0x40) 12339 | | m3 := mload(0x60) 12340 | | m4 := mload(0x80) 12341 | | m5 := mload(0xa0) 12342 | | m6 := mload(0xc0) 12343 | | // Selector of `log(string,uint256,address,bool)`. 12344 | | mstore(0x00, 0x82112a42) 12345 | | mstore(0x20, 0x80) 12346 | | mstore(0x40, p1) 12347 | | mstore(0x60, p2) 12348 | | mstore(0x80, p3) 12349 | | writeString(0xa0, p0) 12350 | | } 12351 | | _sendLogPayload(0x1c, 0xc4); 12352 | | /// @solidity memory-safe-assembly 12353 | | assembly { 12354 | | mstore(0x00, m0) 12355 | | mstore(0x20, m1) 12356 | | mstore(0x40, m2) 12357 | | mstore(0x60, m3) 12358 | | mstore(0x80, m4) 12359 | | mstore(0xa0, m5) 12360 | | mstore(0xc0, m6) 12361 | | } 12362 | | } 12363 | | 12364 | | function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure { 12365 | | bytes32 m0; 12366 | | bytes32 m1; 12367 | | bytes32 m2; 12368 | | bytes32 m3; 12369 | | bytes32 m4; 12370 | | bytes32 m5; 12371 | | bytes32 m6; 12372 | | /// @solidity memory-safe-assembly 12373 | | assembly { 12374 | | function writeString(pos, w) { 12375 | | let length := 0 12376 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12377 | | mstore(pos, length) 12378 | | let shift := sub(256, shl(3, length)) 12379 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12380 | | } 12381 | | m0 := mload(0x00) 12382 | | m1 := mload(0x20) 12383 | | m2 := mload(0x40) 12384 | | m3 := mload(0x60) 12385 | | m4 := mload(0x80) 12386 | | m5 := mload(0xa0) 12387 | | m6 := mload(0xc0) 12388 | | // Selector of `log(string,uint256,address,uint256)`. 12389 | | mstore(0x00, 0x4f04fdc6) 12390 | | mstore(0x20, 0x80) 12391 | | mstore(0x40, p1) 12392 | | mstore(0x60, p2) 12393 | | mstore(0x80, p3) 12394 | | writeString(0xa0, p0) 12395 | | } 12396 | | _sendLogPayload(0x1c, 0xc4); 12397 | | /// @solidity memory-safe-assembly 12398 | | assembly { 12399 | | mstore(0x00, m0) 12400 | | mstore(0x20, m1) 12401 | | mstore(0x40, m2) 12402 | | mstore(0x60, m3) 12403 | | mstore(0x80, m4) 12404 | | mstore(0xa0, m5) 12405 | | mstore(0xc0, m6) 12406 | | } 12407 | | } 12408 | | 12409 | | function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure { 12410 | | bytes32 m0; 12411 | | bytes32 m1; 12412 | | bytes32 m2; 12413 | | bytes32 m3; 12414 | | bytes32 m4; 12415 | | bytes32 m5; 12416 | | bytes32 m6; 12417 | | bytes32 m7; 12418 | | bytes32 m8; 12419 | | /// @solidity memory-safe-assembly 12420 | | assembly { 12421 | | function writeString(pos, w) { 12422 | | let length := 0 12423 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12424 | | mstore(pos, length) 12425 | | let shift := sub(256, shl(3, length)) 12426 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12427 | | } 12428 | | m0 := mload(0x00) 12429 | | m1 := mload(0x20) 12430 | | m2 := mload(0x40) 12431 | | m3 := mload(0x60) 12432 | | m4 := mload(0x80) 12433 | | m5 := mload(0xa0) 12434 | | m6 := mload(0xc0) 12435 | | m7 := mload(0xe0) 12436 | | m8 := mload(0x100) 12437 | | // Selector of `log(string,uint256,address,string)`. 12438 | | mstore(0x00, 0x9ffb2f93) 12439 | | mstore(0x20, 0x80) 12440 | | mstore(0x40, p1) 12441 | | mstore(0x60, p2) 12442 | | mstore(0x80, 0xc0) 12443 | | writeString(0xa0, p0) 12444 | | writeString(0xe0, p3) 12445 | | } 12446 | | _sendLogPayload(0x1c, 0x104); 12447 | | /// @solidity memory-safe-assembly 12448 | | assembly { 12449 | | mstore(0x00, m0) 12450 | | mstore(0x20, m1) 12451 | | mstore(0x40, m2) 12452 | | mstore(0x60, m3) 12453 | | mstore(0x80, m4) 12454 | | mstore(0xa0, m5) 12455 | | mstore(0xc0, m6) 12456 | | mstore(0xe0, m7) 12457 | | mstore(0x100, m8) 12458 | | } 12459 | | } 12460 | | 12461 | | function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure { 12462 | | bytes32 m0; 12463 | | bytes32 m1; 12464 | | bytes32 m2; 12465 | | bytes32 m3; 12466 | | bytes32 m4; 12467 | | bytes32 m5; 12468 | | bytes32 m6; 12469 | | /// @solidity memory-safe-assembly 12470 | | assembly { 12471 | | function writeString(pos, w) { 12472 | | let length := 0 12473 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12474 | | mstore(pos, length) 12475 | | let shift := sub(256, shl(3, length)) 12476 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12477 | | } 12478 | | m0 := mload(0x00) 12479 | | m1 := mload(0x20) 12480 | | m2 := mload(0x40) 12481 | | m3 := mload(0x60) 12482 | | m4 := mload(0x80) 12483 | | m5 := mload(0xa0) 12484 | | m6 := mload(0xc0) 12485 | | // Selector of `log(string,uint256,bool,address)`. 12486 | | mstore(0x00, 0xe0e95b98) 12487 | | mstore(0x20, 0x80) 12488 | | mstore(0x40, p1) 12489 | | mstore(0x60, p2) 12490 | | mstore(0x80, p3) 12491 | | writeString(0xa0, p0) 12492 | | } 12493 | | _sendLogPayload(0x1c, 0xc4); 12494 | | /// @solidity memory-safe-assembly 12495 | | assembly { 12496 | | mstore(0x00, m0) 12497 | | mstore(0x20, m1) 12498 | | mstore(0x40, m2) 12499 | | mstore(0x60, m3) 12500 | | mstore(0x80, m4) 12501 | | mstore(0xa0, m5) 12502 | | mstore(0xc0, m6) 12503 | | } 12504 | | } 12505 | | 12506 | | function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure { 12507 | | bytes32 m0; 12508 | | bytes32 m1; 12509 | | bytes32 m2; 12510 | | bytes32 m3; 12511 | | bytes32 m4; 12512 | | bytes32 m5; 12513 | | bytes32 m6; 12514 | | /// @solidity memory-safe-assembly 12515 | | assembly { 12516 | | function writeString(pos, w) { 12517 | | let length := 0 12518 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12519 | | mstore(pos, length) 12520 | | let shift := sub(256, shl(3, length)) 12521 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12522 | | } 12523 | | m0 := mload(0x00) 12524 | | m1 := mload(0x20) 12525 | | m2 := mload(0x40) 12526 | | m3 := mload(0x60) 12527 | | m4 := mload(0x80) 12528 | | m5 := mload(0xa0) 12529 | | m6 := mload(0xc0) 12530 | | // Selector of `log(string,uint256,bool,bool)`. 12531 | | mstore(0x00, 0x354c36d6) 12532 | | mstore(0x20, 0x80) 12533 | | mstore(0x40, p1) 12534 | | mstore(0x60, p2) 12535 | | mstore(0x80, p3) 12536 | | writeString(0xa0, p0) 12537 | | } 12538 | | _sendLogPayload(0x1c, 0xc4); 12539 | | /// @solidity memory-safe-assembly 12540 | | assembly { 12541 | | mstore(0x00, m0) 12542 | | mstore(0x20, m1) 12543 | | mstore(0x40, m2) 12544 | | mstore(0x60, m3) 12545 | | mstore(0x80, m4) 12546 | | mstore(0xa0, m5) 12547 | | mstore(0xc0, m6) 12548 | | } 12549 | | } 12550 | | 12551 | | function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure { 12552 | | bytes32 m0; 12553 | | bytes32 m1; 12554 | | bytes32 m2; 12555 | | bytes32 m3; 12556 | | bytes32 m4; 12557 | | bytes32 m5; 12558 | | bytes32 m6; 12559 | | /// @solidity memory-safe-assembly 12560 | | assembly { 12561 | | function writeString(pos, w) { 12562 | | let length := 0 12563 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12564 | | mstore(pos, length) 12565 | | let shift := sub(256, shl(3, length)) 12566 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12567 | | } 12568 | | m0 := mload(0x00) 12569 | | m1 := mload(0x20) 12570 | | m2 := mload(0x40) 12571 | | m3 := mload(0x60) 12572 | | m4 := mload(0x80) 12573 | | m5 := mload(0xa0) 12574 | | m6 := mload(0xc0) 12575 | | // Selector of `log(string,uint256,bool,uint256)`. 12576 | | mstore(0x00, 0xe41b6f6f) 12577 | | mstore(0x20, 0x80) 12578 | | mstore(0x40, p1) 12579 | | mstore(0x60, p2) 12580 | | mstore(0x80, p3) 12581 | | writeString(0xa0, p0) 12582 | | } 12583 | | _sendLogPayload(0x1c, 0xc4); 12584 | | /// @solidity memory-safe-assembly 12585 | | assembly { 12586 | | mstore(0x00, m0) 12587 | | mstore(0x20, m1) 12588 | | mstore(0x40, m2) 12589 | | mstore(0x60, m3) 12590 | | mstore(0x80, m4) 12591 | | mstore(0xa0, m5) 12592 | | mstore(0xc0, m6) 12593 | | } 12594 | | } 12595 | | 12596 | | function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure { 12597 | | bytes32 m0; 12598 | | bytes32 m1; 12599 | | bytes32 m2; 12600 | | bytes32 m3; 12601 | | bytes32 m4; 12602 | | bytes32 m5; 12603 | | bytes32 m6; 12604 | | bytes32 m7; 12605 | | bytes32 m8; 12606 | | /// @solidity memory-safe-assembly 12607 | | assembly { 12608 | | function writeString(pos, w) { 12609 | | let length := 0 12610 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12611 | | mstore(pos, length) 12612 | | let shift := sub(256, shl(3, length)) 12613 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12614 | | } 12615 | | m0 := mload(0x00) 12616 | | m1 := mload(0x20) 12617 | | m2 := mload(0x40) 12618 | | m3 := mload(0x60) 12619 | | m4 := mload(0x80) 12620 | | m5 := mload(0xa0) 12621 | | m6 := mload(0xc0) 12622 | | m7 := mload(0xe0) 12623 | | m8 := mload(0x100) 12624 | | // Selector of `log(string,uint256,bool,string)`. 12625 | | mstore(0x00, 0xabf73a98) 12626 | | mstore(0x20, 0x80) 12627 | | mstore(0x40, p1) 12628 | | mstore(0x60, p2) 12629 | | mstore(0x80, 0xc0) 12630 | | writeString(0xa0, p0) 12631 | | writeString(0xe0, p3) 12632 | | } 12633 | | _sendLogPayload(0x1c, 0x104); 12634 | | /// @solidity memory-safe-assembly 12635 | | assembly { 12636 | | mstore(0x00, m0) 12637 | | mstore(0x20, m1) 12638 | | mstore(0x40, m2) 12639 | | mstore(0x60, m3) 12640 | | mstore(0x80, m4) 12641 | | mstore(0xa0, m5) 12642 | | mstore(0xc0, m6) 12643 | | mstore(0xe0, m7) 12644 | | mstore(0x100, m8) 12645 | | } 12646 | | } 12647 | | 12648 | | function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure { 12649 | | bytes32 m0; 12650 | | bytes32 m1; 12651 | | bytes32 m2; 12652 | | bytes32 m3; 12653 | | bytes32 m4; 12654 | | bytes32 m5; 12655 | | bytes32 m6; 12656 | | /// @solidity memory-safe-assembly 12657 | | assembly { 12658 | | function writeString(pos, w) { 12659 | | let length := 0 12660 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12661 | | mstore(pos, length) 12662 | | let shift := sub(256, shl(3, length)) 12663 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12664 | | } 12665 | | m0 := mload(0x00) 12666 | | m1 := mload(0x20) 12667 | | m2 := mload(0x40) 12668 | | m3 := mload(0x60) 12669 | | m4 := mload(0x80) 12670 | | m5 := mload(0xa0) 12671 | | m6 := mload(0xc0) 12672 | | // Selector of `log(string,uint256,uint256,address)`. 12673 | | mstore(0x00, 0xe21de278) 12674 | | mstore(0x20, 0x80) 12675 | | mstore(0x40, p1) 12676 | | mstore(0x60, p2) 12677 | | mstore(0x80, p3) 12678 | | writeString(0xa0, p0) 12679 | | } 12680 | | _sendLogPayload(0x1c, 0xc4); 12681 | | /// @solidity memory-safe-assembly 12682 | | assembly { 12683 | | mstore(0x00, m0) 12684 | | mstore(0x20, m1) 12685 | | mstore(0x40, m2) 12686 | | mstore(0x60, m3) 12687 | | mstore(0x80, m4) 12688 | | mstore(0xa0, m5) 12689 | | mstore(0xc0, m6) 12690 | | } 12691 | | } 12692 | | 12693 | | function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure { 12694 | | bytes32 m0; 12695 | | bytes32 m1; 12696 | | bytes32 m2; 12697 | | bytes32 m3; 12698 | | bytes32 m4; 12699 | | bytes32 m5; 12700 | | bytes32 m6; 12701 | | /// @solidity memory-safe-assembly 12702 | | assembly { 12703 | | function writeString(pos, w) { 12704 | | let length := 0 12705 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12706 | | mstore(pos, length) 12707 | | let shift := sub(256, shl(3, length)) 12708 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12709 | | } 12710 | | m0 := mload(0x00) 12711 | | m1 := mload(0x20) 12712 | | m2 := mload(0x40) 12713 | | m3 := mload(0x60) 12714 | | m4 := mload(0x80) 12715 | | m5 := mload(0xa0) 12716 | | m6 := mload(0xc0) 12717 | | // Selector of `log(string,uint256,uint256,bool)`. 12718 | | mstore(0x00, 0x7626db92) 12719 | | mstore(0x20, 0x80) 12720 | | mstore(0x40, p1) 12721 | | mstore(0x60, p2) 12722 | | mstore(0x80, p3) 12723 | | writeString(0xa0, p0) 12724 | | } 12725 | | _sendLogPayload(0x1c, 0xc4); 12726 | | /// @solidity memory-safe-assembly 12727 | | assembly { 12728 | | mstore(0x00, m0) 12729 | | mstore(0x20, m1) 12730 | | mstore(0x40, m2) 12731 | | mstore(0x60, m3) 12732 | | mstore(0x80, m4) 12733 | | mstore(0xa0, m5) 12734 | | mstore(0xc0, m6) 12735 | | } 12736 | | } 12737 | | 12738 | | function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { 12739 | | bytes32 m0; 12740 | | bytes32 m1; 12741 | | bytes32 m2; 12742 | | bytes32 m3; 12743 | | bytes32 m4; 12744 | | bytes32 m5; 12745 | | bytes32 m6; 12746 | | /// @solidity memory-safe-assembly 12747 | | assembly { 12748 | | function writeString(pos, w) { 12749 | | let length := 0 12750 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12751 | | mstore(pos, length) 12752 | | let shift := sub(256, shl(3, length)) 12753 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12754 | | } 12755 | | m0 := mload(0x00) 12756 | | m1 := mload(0x20) 12757 | | m2 := mload(0x40) 12758 | | m3 := mload(0x60) 12759 | | m4 := mload(0x80) 12760 | | m5 := mload(0xa0) 12761 | | m6 := mload(0xc0) 12762 | | // Selector of `log(string,uint256,uint256,uint256)`. 12763 | | mstore(0x00, 0xa7a87853) 12764 | | mstore(0x20, 0x80) 12765 | | mstore(0x40, p1) 12766 | | mstore(0x60, p2) 12767 | | mstore(0x80, p3) 12768 | | writeString(0xa0, p0) 12769 | | } 12770 | | _sendLogPayload(0x1c, 0xc4); 12771 | | /// @solidity memory-safe-assembly 12772 | | assembly { 12773 | | mstore(0x00, m0) 12774 | | mstore(0x20, m1) 12775 | | mstore(0x40, m2) 12776 | | mstore(0x60, m3) 12777 | | mstore(0x80, m4) 12778 | | mstore(0xa0, m5) 12779 | | mstore(0xc0, m6) 12780 | | } 12781 | | } 12782 | | 12783 | | function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure { 12784 | | bytes32 m0; 12785 | | bytes32 m1; 12786 | | bytes32 m2; 12787 | | bytes32 m3; 12788 | | bytes32 m4; 12789 | | bytes32 m5; 12790 | | bytes32 m6; 12791 | | bytes32 m7; 12792 | | bytes32 m8; 12793 | | /// @solidity memory-safe-assembly 12794 | | assembly { 12795 | | function writeString(pos, w) { 12796 | | let length := 0 12797 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12798 | | mstore(pos, length) 12799 | | let shift := sub(256, shl(3, length)) 12800 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12801 | | } 12802 | | m0 := mload(0x00) 12803 | | m1 := mload(0x20) 12804 | | m2 := mload(0x40) 12805 | | m3 := mload(0x60) 12806 | | m4 := mload(0x80) 12807 | | m5 := mload(0xa0) 12808 | | m6 := mload(0xc0) 12809 | | m7 := mload(0xe0) 12810 | | m8 := mload(0x100) 12811 | | // Selector of `log(string,uint256,uint256,string)`. 12812 | | mstore(0x00, 0x854b3496) 12813 | | mstore(0x20, 0x80) 12814 | | mstore(0x40, p1) 12815 | | mstore(0x60, p2) 12816 | | mstore(0x80, 0xc0) 12817 | | writeString(0xa0, p0) 12818 | | writeString(0xe0, p3) 12819 | | } 12820 | | _sendLogPayload(0x1c, 0x104); 12821 | | /// @solidity memory-safe-assembly 12822 | | assembly { 12823 | | mstore(0x00, m0) 12824 | | mstore(0x20, m1) 12825 | | mstore(0x40, m2) 12826 | | mstore(0x60, m3) 12827 | | mstore(0x80, m4) 12828 | | mstore(0xa0, m5) 12829 | | mstore(0xc0, m6) 12830 | | mstore(0xe0, m7) 12831 | | mstore(0x100, m8) 12832 | | } 12833 | | } 12834 | | 12835 | | function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure { 12836 | | bytes32 m0; 12837 | | bytes32 m1; 12838 | | bytes32 m2; 12839 | | bytes32 m3; 12840 | | bytes32 m4; 12841 | | bytes32 m5; 12842 | | bytes32 m6; 12843 | | bytes32 m7; 12844 | | bytes32 m8; 12845 | | /// @solidity memory-safe-assembly 12846 | | assembly { 12847 | | function writeString(pos, w) { 12848 | | let length := 0 12849 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12850 | | mstore(pos, length) 12851 | | let shift := sub(256, shl(3, length)) 12852 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12853 | | } 12854 | | m0 := mload(0x00) 12855 | | m1 := mload(0x20) 12856 | | m2 := mload(0x40) 12857 | | m3 := mload(0x60) 12858 | | m4 := mload(0x80) 12859 | | m5 := mload(0xa0) 12860 | | m6 := mload(0xc0) 12861 | | m7 := mload(0xe0) 12862 | | m8 := mload(0x100) 12863 | | // Selector of `log(string,uint256,string,address)`. 12864 | | mstore(0x00, 0x7c4632a4) 12865 | | mstore(0x20, 0x80) 12866 | | mstore(0x40, p1) 12867 | | mstore(0x60, 0xc0) 12868 | | mstore(0x80, p3) 12869 | | writeString(0xa0, p0) 12870 | | writeString(0xe0, p2) 12871 | | } 12872 | | _sendLogPayload(0x1c, 0x104); 12873 | | /// @solidity memory-safe-assembly 12874 | | assembly { 12875 | | mstore(0x00, m0) 12876 | | mstore(0x20, m1) 12877 | | mstore(0x40, m2) 12878 | | mstore(0x60, m3) 12879 | | mstore(0x80, m4) 12880 | | mstore(0xa0, m5) 12881 | | mstore(0xc0, m6) 12882 | | mstore(0xe0, m7) 12883 | | mstore(0x100, m8) 12884 | | } 12885 | | } 12886 | | 12887 | | function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure { 12888 | | bytes32 m0; 12889 | | bytes32 m1; 12890 | | bytes32 m2; 12891 | | bytes32 m3; 12892 | | bytes32 m4; 12893 | | bytes32 m5; 12894 | | bytes32 m6; 12895 | | bytes32 m7; 12896 | | bytes32 m8; 12897 | | /// @solidity memory-safe-assembly 12898 | | assembly { 12899 | | function writeString(pos, w) { 12900 | | let length := 0 12901 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12902 | | mstore(pos, length) 12903 | | let shift := sub(256, shl(3, length)) 12904 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12905 | | } 12906 | | m0 := mload(0x00) 12907 | | m1 := mload(0x20) 12908 | | m2 := mload(0x40) 12909 | | m3 := mload(0x60) 12910 | | m4 := mload(0x80) 12911 | | m5 := mload(0xa0) 12912 | | m6 := mload(0xc0) 12913 | | m7 := mload(0xe0) 12914 | | m8 := mload(0x100) 12915 | | // Selector of `log(string,uint256,string,bool)`. 12916 | | mstore(0x00, 0x7d24491d) 12917 | | mstore(0x20, 0x80) 12918 | | mstore(0x40, p1) 12919 | | mstore(0x60, 0xc0) 12920 | | mstore(0x80, p3) 12921 | | writeString(0xa0, p0) 12922 | | writeString(0xe0, p2) 12923 | | } 12924 | | _sendLogPayload(0x1c, 0x104); 12925 | | /// @solidity memory-safe-assembly 12926 | | assembly { 12927 | | mstore(0x00, m0) 12928 | | mstore(0x20, m1) 12929 | | mstore(0x40, m2) 12930 | | mstore(0x60, m3) 12931 | | mstore(0x80, m4) 12932 | | mstore(0xa0, m5) 12933 | | mstore(0xc0, m6) 12934 | | mstore(0xe0, m7) 12935 | | mstore(0x100, m8) 12936 | | } 12937 | | } 12938 | | 12939 | | function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure { 12940 | | bytes32 m0; 12941 | | bytes32 m1; 12942 | | bytes32 m2; 12943 | | bytes32 m3; 12944 | | bytes32 m4; 12945 | | bytes32 m5; 12946 | | bytes32 m6; 12947 | | bytes32 m7; 12948 | | bytes32 m8; 12949 | | /// @solidity memory-safe-assembly 12950 | | assembly { 12951 | | function writeString(pos, w) { 12952 | | let length := 0 12953 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 12954 | | mstore(pos, length) 12955 | | let shift := sub(256, shl(3, length)) 12956 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 12957 | | } 12958 | | m0 := mload(0x00) 12959 | | m1 := mload(0x20) 12960 | | m2 := mload(0x40) 12961 | | m3 := mload(0x60) 12962 | | m4 := mload(0x80) 12963 | | m5 := mload(0xa0) 12964 | | m6 := mload(0xc0) 12965 | | m7 := mload(0xe0) 12966 | | m8 := mload(0x100) 12967 | | // Selector of `log(string,uint256,string,uint256)`. 12968 | | mstore(0x00, 0xc67ea9d1) 12969 | | mstore(0x20, 0x80) 12970 | | mstore(0x40, p1) 12971 | | mstore(0x60, 0xc0) 12972 | | mstore(0x80, p3) 12973 | | writeString(0xa0, p0) 12974 | | writeString(0xe0, p2) 12975 | | } 12976 | | _sendLogPayload(0x1c, 0x104); 12977 | | /// @solidity memory-safe-assembly 12978 | | assembly { 12979 | | mstore(0x00, m0) 12980 | | mstore(0x20, m1) 12981 | | mstore(0x40, m2) 12982 | | mstore(0x60, m3) 12983 | | mstore(0x80, m4) 12984 | | mstore(0xa0, m5) 12985 | | mstore(0xc0, m6) 12986 | | mstore(0xe0, m7) 12987 | | mstore(0x100, m8) 12988 | | } 12989 | | } 12990 | | 12991 | | function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure { 12992 | | bytes32 m0; 12993 | | bytes32 m1; 12994 | | bytes32 m2; 12995 | | bytes32 m3; 12996 | | bytes32 m4; 12997 | | bytes32 m5; 12998 | | bytes32 m6; 12999 | | bytes32 m7; 13000 | | bytes32 m8; 13001 | | bytes32 m9; 13002 | | bytes32 m10; 13003 | | /// @solidity memory-safe-assembly 13004 | | assembly { 13005 | | function writeString(pos, w) { 13006 | | let length := 0 13007 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13008 | | mstore(pos, length) 13009 | | let shift := sub(256, shl(3, length)) 13010 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13011 | | } 13012 | | m0 := mload(0x00) 13013 | | m1 := mload(0x20) 13014 | | m2 := mload(0x40) 13015 | | m3 := mload(0x60) 13016 | | m4 := mload(0x80) 13017 | | m5 := mload(0xa0) 13018 | | m6 := mload(0xc0) 13019 | | m7 := mload(0xe0) 13020 | | m8 := mload(0x100) 13021 | | m9 := mload(0x120) 13022 | | m10 := mload(0x140) 13023 | | // Selector of `log(string,uint256,string,string)`. 13024 | | mstore(0x00, 0x5ab84e1f) 13025 | | mstore(0x20, 0x80) 13026 | | mstore(0x40, p1) 13027 | | mstore(0x60, 0xc0) 13028 | | mstore(0x80, 0x100) 13029 | | writeString(0xa0, p0) 13030 | | writeString(0xe0, p2) 13031 | | writeString(0x120, p3) 13032 | | } 13033 | | _sendLogPayload(0x1c, 0x144); 13034 | | /// @solidity memory-safe-assembly 13035 | | assembly { 13036 | | mstore(0x00, m0) 13037 | | mstore(0x20, m1) 13038 | | mstore(0x40, m2) 13039 | | mstore(0x60, m3) 13040 | | mstore(0x80, m4) 13041 | | mstore(0xa0, m5) 13042 | | mstore(0xc0, m6) 13043 | | mstore(0xe0, m7) 13044 | | mstore(0x100, m8) 13045 | | mstore(0x120, m9) 13046 | | mstore(0x140, m10) 13047 | | } 13048 | | } 13049 | | 13050 | | function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure { 13051 | | bytes32 m0; 13052 | | bytes32 m1; 13053 | | bytes32 m2; 13054 | | bytes32 m3; 13055 | | bytes32 m4; 13056 | | bytes32 m5; 13057 | | bytes32 m6; 13058 | | bytes32 m7; 13059 | | bytes32 m8; 13060 | | /// @solidity memory-safe-assembly 13061 | | assembly { 13062 | | function writeString(pos, w) { 13063 | | let length := 0 13064 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13065 | | mstore(pos, length) 13066 | | let shift := sub(256, shl(3, length)) 13067 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13068 | | } 13069 | | m0 := mload(0x00) 13070 | | m1 := mload(0x20) 13071 | | m2 := mload(0x40) 13072 | | m3 := mload(0x60) 13073 | | m4 := mload(0x80) 13074 | | m5 := mload(0xa0) 13075 | | m6 := mload(0xc0) 13076 | | m7 := mload(0xe0) 13077 | | m8 := mload(0x100) 13078 | | // Selector of `log(string,string,address,address)`. 13079 | | mstore(0x00, 0x439c7bef) 13080 | | mstore(0x20, 0x80) 13081 | | mstore(0x40, 0xc0) 13082 | | mstore(0x60, p2) 13083 | | mstore(0x80, p3) 13084 | | writeString(0xa0, p0) 13085 | | writeString(0xe0, p1) 13086 | | } 13087 | | _sendLogPayload(0x1c, 0x104); 13088 | | /// @solidity memory-safe-assembly 13089 | | assembly { 13090 | | mstore(0x00, m0) 13091 | | mstore(0x20, m1) 13092 | | mstore(0x40, m2) 13093 | | mstore(0x60, m3) 13094 | | mstore(0x80, m4) 13095 | | mstore(0xa0, m5) 13096 | | mstore(0xc0, m6) 13097 | | mstore(0xe0, m7) 13098 | | mstore(0x100, m8) 13099 | | } 13100 | | } 13101 | | 13102 | | function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure { 13103 | | bytes32 m0; 13104 | | bytes32 m1; 13105 | | bytes32 m2; 13106 | | bytes32 m3; 13107 | | bytes32 m4; 13108 | | bytes32 m5; 13109 | | bytes32 m6; 13110 | | bytes32 m7; 13111 | | bytes32 m8; 13112 | | /// @solidity memory-safe-assembly 13113 | | assembly { 13114 | | function writeString(pos, w) { 13115 | | let length := 0 13116 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13117 | | mstore(pos, length) 13118 | | let shift := sub(256, shl(3, length)) 13119 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13120 | | } 13121 | | m0 := mload(0x00) 13122 | | m1 := mload(0x20) 13123 | | m2 := mload(0x40) 13124 | | m3 := mload(0x60) 13125 | | m4 := mload(0x80) 13126 | | m5 := mload(0xa0) 13127 | | m6 := mload(0xc0) 13128 | | m7 := mload(0xe0) 13129 | | m8 := mload(0x100) 13130 | | // Selector of `log(string,string,address,bool)`. 13131 | | mstore(0x00, 0x5ccd4e37) 13132 | | mstore(0x20, 0x80) 13133 | | mstore(0x40, 0xc0) 13134 | | mstore(0x60, p2) 13135 | | mstore(0x80, p3) 13136 | | writeString(0xa0, p0) 13137 | | writeString(0xe0, p1) 13138 | | } 13139 | | _sendLogPayload(0x1c, 0x104); 13140 | | /// @solidity memory-safe-assembly 13141 | | assembly { 13142 | | mstore(0x00, m0) 13143 | | mstore(0x20, m1) 13144 | | mstore(0x40, m2) 13145 | | mstore(0x60, m3) 13146 | | mstore(0x80, m4) 13147 | | mstore(0xa0, m5) 13148 | | mstore(0xc0, m6) 13149 | | mstore(0xe0, m7) 13150 | | mstore(0x100, m8) 13151 | | } 13152 | | } 13153 | | 13154 | | function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure { 13155 | | bytes32 m0; 13156 | | bytes32 m1; 13157 | | bytes32 m2; 13158 | | bytes32 m3; 13159 | | bytes32 m4; 13160 | | bytes32 m5; 13161 | | bytes32 m6; 13162 | | bytes32 m7; 13163 | | bytes32 m8; 13164 | | /// @solidity memory-safe-assembly 13165 | | assembly { 13166 | | function writeString(pos, w) { 13167 | | let length := 0 13168 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13169 | | mstore(pos, length) 13170 | | let shift := sub(256, shl(3, length)) 13171 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13172 | | } 13173 | | m0 := mload(0x00) 13174 | | m1 := mload(0x20) 13175 | | m2 := mload(0x40) 13176 | | m3 := mload(0x60) 13177 | | m4 := mload(0x80) 13178 | | m5 := mload(0xa0) 13179 | | m6 := mload(0xc0) 13180 | | m7 := mload(0xe0) 13181 | | m8 := mload(0x100) 13182 | | // Selector of `log(string,string,address,uint256)`. 13183 | | mstore(0x00, 0x7cc3c607) 13184 | | mstore(0x20, 0x80) 13185 | | mstore(0x40, 0xc0) 13186 | | mstore(0x60, p2) 13187 | | mstore(0x80, p3) 13188 | | writeString(0xa0, p0) 13189 | | writeString(0xe0, p1) 13190 | | } 13191 | | _sendLogPayload(0x1c, 0x104); 13192 | | /// @solidity memory-safe-assembly 13193 | | assembly { 13194 | | mstore(0x00, m0) 13195 | | mstore(0x20, m1) 13196 | | mstore(0x40, m2) 13197 | | mstore(0x60, m3) 13198 | | mstore(0x80, m4) 13199 | | mstore(0xa0, m5) 13200 | | mstore(0xc0, m6) 13201 | | mstore(0xe0, m7) 13202 | | mstore(0x100, m8) 13203 | | } 13204 | | } 13205 | | 13206 | | function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure { 13207 | | bytes32 m0; 13208 | | bytes32 m1; 13209 | | bytes32 m2; 13210 | | bytes32 m3; 13211 | | bytes32 m4; 13212 | | bytes32 m5; 13213 | | bytes32 m6; 13214 | | bytes32 m7; 13215 | | bytes32 m8; 13216 | | bytes32 m9; 13217 | | bytes32 m10; 13218 | | /// @solidity memory-safe-assembly 13219 | | assembly { 13220 | | function writeString(pos, w) { 13221 | | let length := 0 13222 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13223 | | mstore(pos, length) 13224 | | let shift := sub(256, shl(3, length)) 13225 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13226 | | } 13227 | | m0 := mload(0x00) 13228 | | m1 := mload(0x20) 13229 | | m2 := mload(0x40) 13230 | | m3 := mload(0x60) 13231 | | m4 := mload(0x80) 13232 | | m5 := mload(0xa0) 13233 | | m6 := mload(0xc0) 13234 | | m7 := mload(0xe0) 13235 | | m8 := mload(0x100) 13236 | | m9 := mload(0x120) 13237 | | m10 := mload(0x140) 13238 | | // Selector of `log(string,string,address,string)`. 13239 | | mstore(0x00, 0xeb1bff80) 13240 | | mstore(0x20, 0x80) 13241 | | mstore(0x40, 0xc0) 13242 | | mstore(0x60, p2) 13243 | | mstore(0x80, 0x100) 13244 | | writeString(0xa0, p0) 13245 | | writeString(0xe0, p1) 13246 | | writeString(0x120, p3) 13247 | | } 13248 | | _sendLogPayload(0x1c, 0x144); 13249 | | /// @solidity memory-safe-assembly 13250 | | assembly { 13251 | | mstore(0x00, m0) 13252 | | mstore(0x20, m1) 13253 | | mstore(0x40, m2) 13254 | | mstore(0x60, m3) 13255 | | mstore(0x80, m4) 13256 | | mstore(0xa0, m5) 13257 | | mstore(0xc0, m6) 13258 | | mstore(0xe0, m7) 13259 | | mstore(0x100, m8) 13260 | | mstore(0x120, m9) 13261 | | mstore(0x140, m10) 13262 | | } 13263 | | } 13264 | | 13265 | | function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure { 13266 | | bytes32 m0; 13267 | | bytes32 m1; 13268 | | bytes32 m2; 13269 | | bytes32 m3; 13270 | | bytes32 m4; 13271 | | bytes32 m5; 13272 | | bytes32 m6; 13273 | | bytes32 m7; 13274 | | bytes32 m8; 13275 | | /// @solidity memory-safe-assembly 13276 | | assembly { 13277 | | function writeString(pos, w) { 13278 | | let length := 0 13279 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13280 | | mstore(pos, length) 13281 | | let shift := sub(256, shl(3, length)) 13282 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13283 | | } 13284 | | m0 := mload(0x00) 13285 | | m1 := mload(0x20) 13286 | | m2 := mload(0x40) 13287 | | m3 := mload(0x60) 13288 | | m4 := mload(0x80) 13289 | | m5 := mload(0xa0) 13290 | | m6 := mload(0xc0) 13291 | | m7 := mload(0xe0) 13292 | | m8 := mload(0x100) 13293 | | // Selector of `log(string,string,bool,address)`. 13294 | | mstore(0x00, 0xc371c7db) 13295 | | mstore(0x20, 0x80) 13296 | | mstore(0x40, 0xc0) 13297 | | mstore(0x60, p2) 13298 | | mstore(0x80, p3) 13299 | | writeString(0xa0, p0) 13300 | | writeString(0xe0, p1) 13301 | | } 13302 | | _sendLogPayload(0x1c, 0x104); 13303 | | /// @solidity memory-safe-assembly 13304 | | assembly { 13305 | | mstore(0x00, m0) 13306 | | mstore(0x20, m1) 13307 | | mstore(0x40, m2) 13308 | | mstore(0x60, m3) 13309 | | mstore(0x80, m4) 13310 | | mstore(0xa0, m5) 13311 | | mstore(0xc0, m6) 13312 | | mstore(0xe0, m7) 13313 | | mstore(0x100, m8) 13314 | | } 13315 | | } 13316 | | 13317 | | function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure { 13318 | | bytes32 m0; 13319 | | bytes32 m1; 13320 | | bytes32 m2; 13321 | | bytes32 m3; 13322 | | bytes32 m4; 13323 | | bytes32 m5; 13324 | | bytes32 m6; 13325 | | bytes32 m7; 13326 | | bytes32 m8; 13327 | | /// @solidity memory-safe-assembly 13328 | | assembly { 13329 | | function writeString(pos, w) { 13330 | | let length := 0 13331 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13332 | | mstore(pos, length) 13333 | | let shift := sub(256, shl(3, length)) 13334 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13335 | | } 13336 | | m0 := mload(0x00) 13337 | | m1 := mload(0x20) 13338 | | m2 := mload(0x40) 13339 | | m3 := mload(0x60) 13340 | | m4 := mload(0x80) 13341 | | m5 := mload(0xa0) 13342 | | m6 := mload(0xc0) 13343 | | m7 := mload(0xe0) 13344 | | m8 := mload(0x100) 13345 | | // Selector of `log(string,string,bool,bool)`. 13346 | | mstore(0x00, 0x40785869) 13347 | | mstore(0x20, 0x80) 13348 | | mstore(0x40, 0xc0) 13349 | | mstore(0x60, p2) 13350 | | mstore(0x80, p3) 13351 | | writeString(0xa0, p0) 13352 | | writeString(0xe0, p1) 13353 | | } 13354 | | _sendLogPayload(0x1c, 0x104); 13355 | | /// @solidity memory-safe-assembly 13356 | | assembly { 13357 | | mstore(0x00, m0) 13358 | | mstore(0x20, m1) 13359 | | mstore(0x40, m2) 13360 | | mstore(0x60, m3) 13361 | | mstore(0x80, m4) 13362 | | mstore(0xa0, m5) 13363 | | mstore(0xc0, m6) 13364 | | mstore(0xe0, m7) 13365 | | mstore(0x100, m8) 13366 | | } 13367 | | } 13368 | | 13369 | | function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure { 13370 | | bytes32 m0; 13371 | | bytes32 m1; 13372 | | bytes32 m2; 13373 | | bytes32 m3; 13374 | | bytes32 m4; 13375 | | bytes32 m5; 13376 | | bytes32 m6; 13377 | | bytes32 m7; 13378 | | bytes32 m8; 13379 | | /// @solidity memory-safe-assembly 13380 | | assembly { 13381 | | function writeString(pos, w) { 13382 | | let length := 0 13383 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13384 | | mstore(pos, length) 13385 | | let shift := sub(256, shl(3, length)) 13386 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13387 | | } 13388 | | m0 := mload(0x00) 13389 | | m1 := mload(0x20) 13390 | | m2 := mload(0x40) 13391 | | m3 := mload(0x60) 13392 | | m4 := mload(0x80) 13393 | | m5 := mload(0xa0) 13394 | | m6 := mload(0xc0) 13395 | | m7 := mload(0xe0) 13396 | | m8 := mload(0x100) 13397 | | // Selector of `log(string,string,bool,uint256)`. 13398 | | mstore(0x00, 0xd6aefad2) 13399 | | mstore(0x20, 0x80) 13400 | | mstore(0x40, 0xc0) 13401 | | mstore(0x60, p2) 13402 | | mstore(0x80, p3) 13403 | | writeString(0xa0, p0) 13404 | | writeString(0xe0, p1) 13405 | | } 13406 | | _sendLogPayload(0x1c, 0x104); 13407 | | /// @solidity memory-safe-assembly 13408 | | assembly { 13409 | | mstore(0x00, m0) 13410 | | mstore(0x20, m1) 13411 | | mstore(0x40, m2) 13412 | | mstore(0x60, m3) 13413 | | mstore(0x80, m4) 13414 | | mstore(0xa0, m5) 13415 | | mstore(0xc0, m6) 13416 | | mstore(0xe0, m7) 13417 | | mstore(0x100, m8) 13418 | | } 13419 | | } 13420 | | 13421 | | function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure { 13422 | | bytes32 m0; 13423 | | bytes32 m1; 13424 | | bytes32 m2; 13425 | | bytes32 m3; 13426 | | bytes32 m4; 13427 | | bytes32 m5; 13428 | | bytes32 m6; 13429 | | bytes32 m7; 13430 | | bytes32 m8; 13431 | | bytes32 m9; 13432 | | bytes32 m10; 13433 | | /// @solidity memory-safe-assembly 13434 | | assembly { 13435 | | function writeString(pos, w) { 13436 | | let length := 0 13437 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13438 | | mstore(pos, length) 13439 | | let shift := sub(256, shl(3, length)) 13440 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13441 | | } 13442 | | m0 := mload(0x00) 13443 | | m1 := mload(0x20) 13444 | | m2 := mload(0x40) 13445 | | m3 := mload(0x60) 13446 | | m4 := mload(0x80) 13447 | | m5 := mload(0xa0) 13448 | | m6 := mload(0xc0) 13449 | | m7 := mload(0xe0) 13450 | | m8 := mload(0x100) 13451 | | m9 := mload(0x120) 13452 | | m10 := mload(0x140) 13453 | | // Selector of `log(string,string,bool,string)`. 13454 | | mstore(0x00, 0x5e84b0ea) 13455 | | mstore(0x20, 0x80) 13456 | | mstore(0x40, 0xc0) 13457 | | mstore(0x60, p2) 13458 | | mstore(0x80, 0x100) 13459 | | writeString(0xa0, p0) 13460 | | writeString(0xe0, p1) 13461 | | writeString(0x120, p3) 13462 | | } 13463 | | _sendLogPayload(0x1c, 0x144); 13464 | | /// @solidity memory-safe-assembly 13465 | | assembly { 13466 | | mstore(0x00, m0) 13467 | | mstore(0x20, m1) 13468 | | mstore(0x40, m2) 13469 | | mstore(0x60, m3) 13470 | | mstore(0x80, m4) 13471 | | mstore(0xa0, m5) 13472 | | mstore(0xc0, m6) 13473 | | mstore(0xe0, m7) 13474 | | mstore(0x100, m8) 13475 | | mstore(0x120, m9) 13476 | | mstore(0x140, m10) 13477 | | } 13478 | | } 13479 | | 13480 | | function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure { 13481 | | bytes32 m0; 13482 | | bytes32 m1; 13483 | | bytes32 m2; 13484 | | bytes32 m3; 13485 | | bytes32 m4; 13486 | | bytes32 m5; 13487 | | bytes32 m6; 13488 | | bytes32 m7; 13489 | | bytes32 m8; 13490 | | /// @solidity memory-safe-assembly 13491 | | assembly { 13492 | | function writeString(pos, w) { 13493 | | let length := 0 13494 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13495 | | mstore(pos, length) 13496 | | let shift := sub(256, shl(3, length)) 13497 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13498 | | } 13499 | | m0 := mload(0x00) 13500 | | m1 := mload(0x20) 13501 | | m2 := mload(0x40) 13502 | | m3 := mload(0x60) 13503 | | m4 := mload(0x80) 13504 | | m5 := mload(0xa0) 13505 | | m6 := mload(0xc0) 13506 | | m7 := mload(0xe0) 13507 | | m8 := mload(0x100) 13508 | | // Selector of `log(string,string,uint256,address)`. 13509 | | mstore(0x00, 0x1023f7b2) 13510 | | mstore(0x20, 0x80) 13511 | | mstore(0x40, 0xc0) 13512 | | mstore(0x60, p2) 13513 | | mstore(0x80, p3) 13514 | | writeString(0xa0, p0) 13515 | | writeString(0xe0, p1) 13516 | | } 13517 | | _sendLogPayload(0x1c, 0x104); 13518 | | /// @solidity memory-safe-assembly 13519 | | assembly { 13520 | | mstore(0x00, m0) 13521 | | mstore(0x20, m1) 13522 | | mstore(0x40, m2) 13523 | | mstore(0x60, m3) 13524 | | mstore(0x80, m4) 13525 | | mstore(0xa0, m5) 13526 | | mstore(0xc0, m6) 13527 | | mstore(0xe0, m7) 13528 | | mstore(0x100, m8) 13529 | | } 13530 | | } 13531 | | 13532 | | function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure { 13533 | | bytes32 m0; 13534 | | bytes32 m1; 13535 | | bytes32 m2; 13536 | | bytes32 m3; 13537 | | bytes32 m4; 13538 | | bytes32 m5; 13539 | | bytes32 m6; 13540 | | bytes32 m7; 13541 | | bytes32 m8; 13542 | | /// @solidity memory-safe-assembly 13543 | | assembly { 13544 | | function writeString(pos, w) { 13545 | | let length := 0 13546 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13547 | | mstore(pos, length) 13548 | | let shift := sub(256, shl(3, length)) 13549 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13550 | | } 13551 | | m0 := mload(0x00) 13552 | | m1 := mload(0x20) 13553 | | m2 := mload(0x40) 13554 | | m3 := mload(0x60) 13555 | | m4 := mload(0x80) 13556 | | m5 := mload(0xa0) 13557 | | m6 := mload(0xc0) 13558 | | m7 := mload(0xe0) 13559 | | m8 := mload(0x100) 13560 | | // Selector of `log(string,string,uint256,bool)`. 13561 | | mstore(0x00, 0xc3a8a654) 13562 | | mstore(0x20, 0x80) 13563 | | mstore(0x40, 0xc0) 13564 | | mstore(0x60, p2) 13565 | | mstore(0x80, p3) 13566 | | writeString(0xa0, p0) 13567 | | writeString(0xe0, p1) 13568 | | } 13569 | | _sendLogPayload(0x1c, 0x104); 13570 | | /// @solidity memory-safe-assembly 13571 | | assembly { 13572 | | mstore(0x00, m0) 13573 | | mstore(0x20, m1) 13574 | | mstore(0x40, m2) 13575 | | mstore(0x60, m3) 13576 | | mstore(0x80, m4) 13577 | | mstore(0xa0, m5) 13578 | | mstore(0xc0, m6) 13579 | | mstore(0xe0, m7) 13580 | | mstore(0x100, m8) 13581 | | } 13582 | | } 13583 | | 13584 | | function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure { 13585 | | bytes32 m0; 13586 | | bytes32 m1; 13587 | | bytes32 m2; 13588 | | bytes32 m3; 13589 | | bytes32 m4; 13590 | | bytes32 m5; 13591 | | bytes32 m6; 13592 | | bytes32 m7; 13593 | | bytes32 m8; 13594 | | /// @solidity memory-safe-assembly 13595 | | assembly { 13596 | | function writeString(pos, w) { 13597 | | let length := 0 13598 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13599 | | mstore(pos, length) 13600 | | let shift := sub(256, shl(3, length)) 13601 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13602 | | } 13603 | | m0 := mload(0x00) 13604 | | m1 := mload(0x20) 13605 | | m2 := mload(0x40) 13606 | | m3 := mload(0x60) 13607 | | m4 := mload(0x80) 13608 | | m5 := mload(0xa0) 13609 | | m6 := mload(0xc0) 13610 | | m7 := mload(0xe0) 13611 | | m8 := mload(0x100) 13612 | | // Selector of `log(string,string,uint256,uint256)`. 13613 | | mstore(0x00, 0xf45d7d2c) 13614 | | mstore(0x20, 0x80) 13615 | | mstore(0x40, 0xc0) 13616 | | mstore(0x60, p2) 13617 | | mstore(0x80, p3) 13618 | | writeString(0xa0, p0) 13619 | | writeString(0xe0, p1) 13620 | | } 13621 | | _sendLogPayload(0x1c, 0x104); 13622 | | /// @solidity memory-safe-assembly 13623 | | assembly { 13624 | | mstore(0x00, m0) 13625 | | mstore(0x20, m1) 13626 | | mstore(0x40, m2) 13627 | | mstore(0x60, m3) 13628 | | mstore(0x80, m4) 13629 | | mstore(0xa0, m5) 13630 | | mstore(0xc0, m6) 13631 | | mstore(0xe0, m7) 13632 | | mstore(0x100, m8) 13633 | | } 13634 | | } 13635 | | 13636 | | function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure { 13637 | | bytes32 m0; 13638 | | bytes32 m1; 13639 | | bytes32 m2; 13640 | | bytes32 m3; 13641 | | bytes32 m4; 13642 | | bytes32 m5; 13643 | | bytes32 m6; 13644 | | bytes32 m7; 13645 | | bytes32 m8; 13646 | | bytes32 m9; 13647 | | bytes32 m10; 13648 | | /// @solidity memory-safe-assembly 13649 | | assembly { 13650 | | function writeString(pos, w) { 13651 | | let length := 0 13652 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13653 | | mstore(pos, length) 13654 | | let shift := sub(256, shl(3, length)) 13655 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13656 | | } 13657 | | m0 := mload(0x00) 13658 | | m1 := mload(0x20) 13659 | | m2 := mload(0x40) 13660 | | m3 := mload(0x60) 13661 | | m4 := mload(0x80) 13662 | | m5 := mload(0xa0) 13663 | | m6 := mload(0xc0) 13664 | | m7 := mload(0xe0) 13665 | | m8 := mload(0x100) 13666 | | m9 := mload(0x120) 13667 | | m10 := mload(0x140) 13668 | | // Selector of `log(string,string,uint256,string)`. 13669 | | mstore(0x00, 0x5d1a971a) 13670 | | mstore(0x20, 0x80) 13671 | | mstore(0x40, 0xc0) 13672 | | mstore(0x60, p2) 13673 | | mstore(0x80, 0x100) 13674 | | writeString(0xa0, p0) 13675 | | writeString(0xe0, p1) 13676 | | writeString(0x120, p3) 13677 | | } 13678 | | _sendLogPayload(0x1c, 0x144); 13679 | | /// @solidity memory-safe-assembly 13680 | | assembly { 13681 | | mstore(0x00, m0) 13682 | | mstore(0x20, m1) 13683 | | mstore(0x40, m2) 13684 | | mstore(0x60, m3) 13685 | | mstore(0x80, m4) 13686 | | mstore(0xa0, m5) 13687 | | mstore(0xc0, m6) 13688 | | mstore(0xe0, m7) 13689 | | mstore(0x100, m8) 13690 | | mstore(0x120, m9) 13691 | | mstore(0x140, m10) 13692 | | } 13693 | | } 13694 | | 13695 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure { 13696 | | bytes32 m0; 13697 | | bytes32 m1; 13698 | | bytes32 m2; 13699 | | bytes32 m3; 13700 | | bytes32 m4; 13701 | | bytes32 m5; 13702 | | bytes32 m6; 13703 | | bytes32 m7; 13704 | | bytes32 m8; 13705 | | bytes32 m9; 13706 | | bytes32 m10; 13707 | | /// @solidity memory-safe-assembly 13708 | | assembly { 13709 | | function writeString(pos, w) { 13710 | | let length := 0 13711 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13712 | | mstore(pos, length) 13713 | | let shift := sub(256, shl(3, length)) 13714 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13715 | | } 13716 | | m0 := mload(0x00) 13717 | | m1 := mload(0x20) 13718 | | m2 := mload(0x40) 13719 | | m3 := mload(0x60) 13720 | | m4 := mload(0x80) 13721 | | m5 := mload(0xa0) 13722 | | m6 := mload(0xc0) 13723 | | m7 := mload(0xe0) 13724 | | m8 := mload(0x100) 13725 | | m9 := mload(0x120) 13726 | | m10 := mload(0x140) 13727 | | // Selector of `log(string,string,string,address)`. 13728 | | mstore(0x00, 0x6d572f44) 13729 | | mstore(0x20, 0x80) 13730 | | mstore(0x40, 0xc0) 13731 | | mstore(0x60, 0x100) 13732 | | mstore(0x80, p3) 13733 | | writeString(0xa0, p0) 13734 | | writeString(0xe0, p1) 13735 | | writeString(0x120, p2) 13736 | | } 13737 | | _sendLogPayload(0x1c, 0x144); 13738 | | /// @solidity memory-safe-assembly 13739 | | assembly { 13740 | | mstore(0x00, m0) 13741 | | mstore(0x20, m1) 13742 | | mstore(0x40, m2) 13743 | | mstore(0x60, m3) 13744 | | mstore(0x80, m4) 13745 | | mstore(0xa0, m5) 13746 | | mstore(0xc0, m6) 13747 | | mstore(0xe0, m7) 13748 | | mstore(0x100, m8) 13749 | | mstore(0x120, m9) 13750 | | mstore(0x140, m10) 13751 | | } 13752 | | } 13753 | | 13754 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure { 13755 | | bytes32 m0; 13756 | | bytes32 m1; 13757 | | bytes32 m2; 13758 | | bytes32 m3; 13759 | | bytes32 m4; 13760 | | bytes32 m5; 13761 | | bytes32 m6; 13762 | | bytes32 m7; 13763 | | bytes32 m8; 13764 | | bytes32 m9; 13765 | | bytes32 m10; 13766 | | /// @solidity memory-safe-assembly 13767 | | assembly { 13768 | | function writeString(pos, w) { 13769 | | let length := 0 13770 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13771 | | mstore(pos, length) 13772 | | let shift := sub(256, shl(3, length)) 13773 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13774 | | } 13775 | | m0 := mload(0x00) 13776 | | m1 := mload(0x20) 13777 | | m2 := mload(0x40) 13778 | | m3 := mload(0x60) 13779 | | m4 := mload(0x80) 13780 | | m5 := mload(0xa0) 13781 | | m6 := mload(0xc0) 13782 | | m7 := mload(0xe0) 13783 | | m8 := mload(0x100) 13784 | | m9 := mload(0x120) 13785 | | m10 := mload(0x140) 13786 | | // Selector of `log(string,string,string,bool)`. 13787 | | mstore(0x00, 0x2c1754ed) 13788 | | mstore(0x20, 0x80) 13789 | | mstore(0x40, 0xc0) 13790 | | mstore(0x60, 0x100) 13791 | | mstore(0x80, p3) 13792 | | writeString(0xa0, p0) 13793 | | writeString(0xe0, p1) 13794 | | writeString(0x120, p2) 13795 | | } 13796 | | _sendLogPayload(0x1c, 0x144); 13797 | | /// @solidity memory-safe-assembly 13798 | | assembly { 13799 | | mstore(0x00, m0) 13800 | | mstore(0x20, m1) 13801 | | mstore(0x40, m2) 13802 | | mstore(0x60, m3) 13803 | | mstore(0x80, m4) 13804 | | mstore(0xa0, m5) 13805 | | mstore(0xc0, m6) 13806 | | mstore(0xe0, m7) 13807 | | mstore(0x100, m8) 13808 | | mstore(0x120, m9) 13809 | | mstore(0x140, m10) 13810 | | } 13811 | | } 13812 | | 13813 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure { 13814 | | bytes32 m0; 13815 | | bytes32 m1; 13816 | | bytes32 m2; 13817 | | bytes32 m3; 13818 | | bytes32 m4; 13819 | | bytes32 m5; 13820 | | bytes32 m6; 13821 | | bytes32 m7; 13822 | | bytes32 m8; 13823 | | bytes32 m9; 13824 | | bytes32 m10; 13825 | | /// @solidity memory-safe-assembly 13826 | | assembly { 13827 | | function writeString(pos, w) { 13828 | | let length := 0 13829 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13830 | | mstore(pos, length) 13831 | | let shift := sub(256, shl(3, length)) 13832 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13833 | | } 13834 | | m0 := mload(0x00) 13835 | | m1 := mload(0x20) 13836 | | m2 := mload(0x40) 13837 | | m3 := mload(0x60) 13838 | | m4 := mload(0x80) 13839 | | m5 := mload(0xa0) 13840 | | m6 := mload(0xc0) 13841 | | m7 := mload(0xe0) 13842 | | m8 := mload(0x100) 13843 | | m9 := mload(0x120) 13844 | | m10 := mload(0x140) 13845 | | // Selector of `log(string,string,string,uint256)`. 13846 | | mstore(0x00, 0x8eafb02b) 13847 | | mstore(0x20, 0x80) 13848 | | mstore(0x40, 0xc0) 13849 | | mstore(0x60, 0x100) 13850 | | mstore(0x80, p3) 13851 | | writeString(0xa0, p0) 13852 | | writeString(0xe0, p1) 13853 | | writeString(0x120, p2) 13854 | | } 13855 | | _sendLogPayload(0x1c, 0x144); 13856 | | /// @solidity memory-safe-assembly 13857 | | assembly { 13858 | | mstore(0x00, m0) 13859 | | mstore(0x20, m1) 13860 | | mstore(0x40, m2) 13861 | | mstore(0x60, m3) 13862 | | mstore(0x80, m4) 13863 | | mstore(0xa0, m5) 13864 | | mstore(0xc0, m6) 13865 | | mstore(0xe0, m7) 13866 | | mstore(0x100, m8) 13867 | | mstore(0x120, m9) 13868 | | mstore(0x140, m10) 13869 | | } 13870 | | } 13871 | | 13872 | | function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure { 13873 | | bytes32 m0; 13874 | | bytes32 m1; 13875 | | bytes32 m2; 13876 | | bytes32 m3; 13877 | | bytes32 m4; 13878 | | bytes32 m5; 13879 | | bytes32 m6; 13880 | | bytes32 m7; 13881 | | bytes32 m8; 13882 | | bytes32 m9; 13883 | | bytes32 m10; 13884 | | bytes32 m11; 13885 | | bytes32 m12; 13886 | | /// @solidity memory-safe-assembly 13887 | | assembly { 13888 | | function writeString(pos, w) { 13889 | | let length := 0 13890 | | for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } } 13891 | | mstore(pos, length) 13892 | | let shift := sub(256, shl(3, length)) 13893 | | mstore(add(pos, 0x20), shl(shift, shr(shift, w))) 13894 | | } 13895 | | m0 := mload(0x00) 13896 | | m1 := mload(0x20) 13897 | | m2 := mload(0x40) 13898 | | m3 := mload(0x60) 13899 | | m4 := mload(0x80) 13900 | | m5 := mload(0xa0) 13901 | | m6 := mload(0xc0) 13902 | | m7 := mload(0xe0) 13903 | | m8 := mload(0x100) 13904 | | m9 := mload(0x120) 13905 | | m10 := mload(0x140) 13906 | | m11 := mload(0x160) 13907 | | m12 := mload(0x180) 13908 | | // Selector of `log(string,string,string,string)`. 13909 | | mstore(0x00, 0xde68f20a) 13910 | | mstore(0x20, 0x80) 13911 | | mstore(0x40, 0xc0) 13912 | | mstore(0x60, 0x100) 13913 | | mstore(0x80, 0x140) 13914 | | writeString(0xa0, p0) 13915 | | writeString(0xe0, p1) 13916 | | writeString(0x120, p2) 13917 | | writeString(0x160, p3) 13918 | | } 13919 | | _sendLogPayload(0x1c, 0x184); 13920 | | /// @solidity memory-safe-assembly 13921 | | assembly { 13922 | | mstore(0x00, m0) 13923 | | mstore(0x20, m1) 13924 | | mstore(0x40, m2) 13925 | | mstore(0x60, m3) 13926 | | mstore(0x80, m4) 13927 | | mstore(0xa0, m5) 13928 | | mstore(0xc0, m6) 13929 | | mstore(0xe0, m7) 13930 | | mstore(0x100, m8) 13931 | | mstore(0x120, m9) 13932 | | mstore(0x140, m10) 13933 | | mstore(0x160, m11) 13934 | | mstore(0x180, m12) 13935 | | } 13936 | | } 13937 | | } 13938 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/Constants.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | library Constants { 5 | | // https://docs.soliditylang.org/en/latest/control-structures.html#panic-via-assert-and-error-via-require 6 | | // 0x00: Used for generic compiler inserted panics. 7 | | // 0x01: If you call assert with an argument that evaluates to false. 8 | | // 0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block. 9 | | // 0x12; If you divide or modulo by zero (e.g. 5 / 0 or 23 % 0). 10 | | // 0x21: If you convert a value that is too big or negative into an enum type. 11 | | // 0x22: If you access a storage byte array that is incorrectly encoded. 12 | | // 0x31: If you call .pop() on an empty array. 13 | | // 0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0). 14 | | // 0x41: If you allocate too much memory or create an array that is too large. 15 | | // 0x51: If you call a zero-initialized variable of internal function type. 16 | | uint256 public constant PANIC_GENERAL = 0x00; 17 | | uint256 public constant PANIC_ASSERT = 0x01; 18 | | uint256 public constant PANIC_ARITHMETIC = 0x11; 19 | | uint256 public constant PANIC_DIVISION_BY_ZERO = 0x12; 20 | | uint256 public constant PANIC_ENUM_OUT_OF_BOUNDS = 0x21; 21 | | uint256 public constant PANIC_STORAGE_BYTES_ARRAY_ENCODING = 0x22; 22 | | uint256 public constant PANIC_POP_EMPTY_ARRAY = 0x31; 23 | | uint256 public constant PANIC_ARRAY_OUT_OF_BOUNDS = 0x32; 24 | | uint256 public constant PANIC_ALLOC_TOO_MUCH_MEMORY = 0x41; 25 | | uint256 public constant PANIC_ZERO_INIT_INTERNAL_FUNCTION = 0x51; 26 | | 27 | | address public constant ADDRESS_CHEATS = 28 | | 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/FuzzBase.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {Fuzzlib} from "./Fuzzlib.sol"; 5 | | import {PlatformCrytic} from "./platform/PlatformCrytic.sol"; 6 | | 7 | | abstract contract FuzzBase { 8 | | Fuzzlib internal fl = new Fuzzlib(); 9 | | 10 | | constructor() { 11 | | fl.setPlatform(address(new PlatformCrytic())); 12 | | } 13 | | } 14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/FuzzLibString.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | /// @notice Efficient library for creating string representations of integers. 5 | | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) 6 | | /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol) 7 | | /// @author Modified from Crytic Properties (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) 8 | * | library FuzzLibString { 9 | | bytes16 internal constant HEX_DIGITS = "0123456789abcdef"; 10 | | 11 | | function toString(int256 value) internal pure returns (string memory str) { 12 | | uint256 absValue = value >= 0 ? uint256(value) : uint256(-value); 13 | | str = toString(absValue); 14 | | 15 | | if (value < 0) { 16 | | str = string(abi.encodePacked("-", str)); 17 | | } 18 | | } 19 | | 20 | * | function toString(uint256 value) internal pure returns (string memory str) { 21 | | /// @solidity memory-safe-assembly 22 | * | assembly { 23 | | // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes 24 | | // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the 25 | | // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. 26 | * | let newFreeMemoryPointer := add(mload(0x40), 160) 27 | | 28 | | // Update the free memory pointer to avoid overriding our string. 29 | * | mstore(0x40, newFreeMemoryPointer) 30 | | 31 | | // Assign str to the end of the zone of newly allocated memory. 32 | * | str := sub(newFreeMemoryPointer, 32) 33 | | 34 | | // Clean the last word of memory it may not be overwritten. 35 | * | mstore(str, 0) 36 | | 37 | | // Cache the end of the memory to calculate the length later. 38 | * | let end := str 39 | | 40 | | // We write the string from rightmost digit to leftmost digit. 41 | | // The following is essentially a do-while loop that also handles the zero case. 42 | | // prettier-ignore 43 | * | for { let temp := value } 1 {} { 44 | | // Move the pointer 1 byte to the left. 45 | * | str := sub(str, 1) 46 | | 47 | | // Write the character to the pointer. 48 | | // The ASCII index of the '0' character is 48. 49 | * | mstore8(str, add(48, mod(temp, 10))) 50 | | 51 | | // Keep dividing temp until zero. 52 | * | temp := div(temp, 10) 53 | | 54 | | // prettier-ignore 55 | * | if iszero(temp) { break } 56 | | } 57 | | 58 | | // Compute and cache the final total length of the string. 59 | * | let length := sub(end, str) 60 | | 61 | | // Move the pointer 32 bytes leftwards to make room for the length. 62 | * | str := sub(str, 32) 63 | | 64 | | // Store the string's length at the start of memory allocated for our string. 65 | * | mstore(str, length) 66 | | } 67 | | } 68 | | 69 | | function toString(address value) internal pure returns (string memory str) { 70 | | bytes memory s = new bytes(40); 71 | | for (uint256 i = 0; i < 20; i++) { 72 | | bytes1 b = bytes1( 73 | | uint8(uint256(uint160(value)) / (2**(8 * (19 - i)))) 74 | | ); 75 | | bytes1 hi = bytes1(uint8(b) / 16); 76 | | bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); 77 | | s[2 * i] = char(hi); 78 | | s[2 * i + 1] = char(lo); 79 | | } 80 | | return string(s); 81 | | } 82 | | 83 | | function char(bytes1 b) internal pure returns (bytes1 c) { 84 | | if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); 85 | | else return bytes1(uint8(b) + 0x57); 86 | | } 87 | | 88 | | // based on OZ's toHexString 89 | | // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Strings.sol 90 | | function toHexString(bytes memory value) 91 | | internal 92 | | pure 93 | | returns (string memory) 94 | | { 95 | | bytes memory buffer = new bytes(2 * value.length + 2); 96 | | buffer[0] = "0"; 97 | | buffer[1] = "x"; 98 | | for (uint256 i = 0; i < value.length; i++) { 99 | | uint8 valueByte = uint8(value[i]); 100 | | buffer[2 * i + 2] = HEX_DIGITS[valueByte >> 4]; 101 | | buffer[2 * i + 3] = HEX_DIGITS[valueByte & 0xf]; 102 | | } 103 | | return string(buffer); 104 | | } 105 | | 106 | | // https://ethereum.stackexchange.com/a/83577 107 | | function getRevertMsg(bytes memory returnData) 108 | | internal 109 | | pure 110 | | returns (string memory) 111 | | { 112 | | // Check that the data has the right size: 4 bytes for signature + 32 bytes for panic code 113 | | if (returnData.length == 4 + 32) { 114 | | // Check that the data starts with the Panic signature 115 | | bytes4 panicSignature = bytes4(keccak256(bytes("Panic(uint256)"))); 116 | | for (uint256 i = 0; i < 4; i++) { 117 | | if (returnData[i] != panicSignature[i]) 118 | | return "Undefined signature"; 119 | | } 120 | | 121 | | uint256 panicCode; 122 | | for (uint256 i = 4; i < 36; i++) { 123 | | panicCode = panicCode << 8; 124 | | panicCode |= uint8(returnData[i]); 125 | | } 126 | | 127 | | // Now convert the panic code into its string representation 128 | | if (panicCode == 17) { 129 | | return "Panic(17)"; 130 | | } 131 | | 132 | | // Add other panic codes as needed or return a generic "Unknown panic" 133 | | return "Undefined panic code"; 134 | | } 135 | | 136 | | // If the returnData length is less than 68, then the transaction failed silently (without a revert message) 137 | | if (returnData.length < 68) return "Transaction reverted silently"; 138 | | 139 | | assembly { 140 | | // Slice the sighash. 141 | | returnData := add(returnData, 0x04) 142 | | } 143 | | return abi.decode(returnData, (string)); // All that remains is the revert string 144 | | } 145 | | 146 | | function isRevertReasonEqual(bytes memory returnData, string memory reason) 147 | | internal 148 | | pure 149 | | returns (bool) 150 | | { 151 | | return (keccak256(abi.encodePacked(getRevertMsg(returnData))) == 152 | | keccak256(abi.encodePacked(reason))); 153 | | } 154 | | } 155 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/Fuzzlib.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {HelperBase} from "./helpers/HelperBase.sol"; 5 | | import {HelperAssert} from "./helpers/HelperAssert.sol"; 6 | | import {HelperClamp} from "./helpers/HelperClamp.sol"; 7 | | import {HelperLog} from "./helpers/HelperLog.sol"; 8 | | import {HelperMath} from "./helpers/HelperMath.sol"; 9 | | import {HelperRandom} from "./helpers/HelperRandom.sol"; 10 | | 11 | * | contract Fuzzlib is 12 | | HelperBase, 13 | | HelperAssert, 14 | | HelperClamp, 15 | | HelperLog, 16 | | HelperMath, 17 | | HelperRandom 18 | | {} 19 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/IHevm.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {Constants} from "./Constants.sol"; 5 | | 6 | | interface IHevm { 7 | | // Set block.timestamp to newTimestamp 8 | | function warp(uint256 newTimestamp) external; 9 | | 10 | | // Set block.number to newNumber 11 | | function roll(uint256 newNumber) external; 12 | | 13 | | // Add the condition b to the assumption base for the current branch 14 | | // This function is almost identical to require 15 | | function assume(bool b) external; 16 | | 17 | | // Sets the eth balance of usr to amt 18 | | function deal(address usr, uint256 amt) external; 19 | | 20 | | // Loads a storage slot from an address 21 | | function load(address where, bytes32 slot) external returns (bytes32); 22 | | 23 | | // Stores a value to an address' storage slot 24 | | function store(address where, bytes32 slot, bytes32 value) external; 25 | | 26 | | // Signs data (privateKey, digest) => (v, r, s) 27 | | function sign( 28 | | uint256 privateKey, 29 | | bytes32 digest 30 | | ) external returns (uint8 v, bytes32 r, bytes32 s); 31 | | 32 | | // Gets address for a given private key 33 | | function addr(uint256 privateKey) external returns (address addr); 34 | | 35 | | // Performs a foreign function call via terminal 36 | | function ffi( 37 | | string[] calldata inputs 38 | | ) external returns (bytes memory result); 39 | | 40 | | // Performs the next smart contract call with specified `msg.sender` 41 | | function prank(address newSender) external; 42 | | 43 | | // Creates a new fork with the given endpoint and the latest block and returns the identifier of the fork 44 | | function createFork(string calldata urlOrAlias) external returns (uint256); 45 | | 46 | | // Takes a fork identifier created by createFork and sets the corresponding forked state as active 47 | | function selectFork(uint256 forkId) external; 48 | | 49 | | // Returns the identifier of the current fork 50 | | function activeFork() external returns (uint256); 51 | | 52 | | // Labels the address in traces 53 | | function label(address addr, string calldata label) external; 54 | | } 55 | | 56 | | // Don't use Constants.ADDRESS_CHEATS to support older Solidity versions 57 | | IHevm constant vm = IHevm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); 58 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperAssert.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "./HelperBase.sol"; 5 | | 6 | | import "../FuzzLibString.sol"; 7 | | 8 | | /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) 9 | | abstract contract HelperAssert is HelperBase { 10 | | event AssertFail(string); 11 | | event AssertEqFail(string); 12 | | event AssertNeqFail(string); 13 | | event AssertGteFail(string); 14 | | event AssertGtFail(string); 15 | | event AssertLteFail(string); 16 | | event AssertLtFail(string); 17 | | 18 | * | function t(bool b, string memory reason) public { 19 | * | if (!b) { 20 | * | emit AssertFail(reason); 21 | * | platform.assertFail(); 22 | | } 23 | | } 24 | | 25 | | /// @notice asserts that a is equal to b. Violations are logged using reason. 26 | * | function eq( 27 | | uint256 a, 28 | | uint256 b, 29 | | string memory reason 30 | | ) public { 31 | * | if (a != b) { 32 | | string memory aStr = FuzzLibString.toString(a); 33 | | string memory bStr = FuzzLibString.toString(b); 34 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason); 35 | | emit AssertEqFail(assertMsg); 36 | | platform.assertFail(); 37 | | } 38 | | } 39 | | 40 | | /// @notice int256 version of eq 41 | | function eq( 42 | | int256 a, 43 | | int256 b, 44 | | string memory reason 45 | | ) public { 46 | | if (a != b) { 47 | | string memory aStr = FuzzLibString.toString(a); 48 | | string memory bStr = FuzzLibString.toString(b); 49 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason); 50 | | emit AssertEqFail(assertMsg); 51 | | platform.assertFail(); 52 | | } 53 | | } 54 | | 55 | | /// @notice bool version of eq 56 | | function eq( 57 | | bool a, 58 | | bool b, 59 | | string memory reason 60 | | ) public { 61 | | if (a != b) { 62 | | string memory aStr = a ? "true" : "false"; 63 | | string memory bStr = b ? "true" : "false"; 64 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason); 65 | | emit AssertEqFail(assertMsg); 66 | | platform.assertFail(); 67 | | } 68 | | } 69 | | 70 | | /// @notice address version of eq 71 | | function eq( 72 | | address a, 73 | | address b, 74 | | string memory reason 75 | | ) public { 76 | | if (a != b) { 77 | | string memory aStr = FuzzLibString.toString(a); 78 | | string memory bStr = FuzzLibString.toString(b); 79 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason); 80 | | emit AssertEqFail(assertMsg); 81 | | platform.assertFail(); 82 | | } 83 | | } 84 | | 85 | | /// @notice bytes4 version of eq 86 | | function eq( 87 | | bytes4 a, 88 | | bytes4 b, 89 | | string memory reason 90 | | ) public { 91 | | if (a != b) { 92 | | bytes memory aBytes = abi.encodePacked(a); 93 | | bytes memory bBytes = abi.encodePacked(b); 94 | | string memory aStr = FuzzLibString.toHexString(aBytes); 95 | | string memory bStr = FuzzLibString.toHexString(bBytes); 96 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "!=", reason); 97 | | emit AssertEqFail(assertMsg); 98 | | platform.assertFail(); 99 | | } 100 | | } 101 | | 102 | | /// @notice asserts that a is not equal to b. Violations are logged using reason. 103 | * | function neq( 104 | | uint256 a, 105 | | uint256 b, 106 | | string memory reason 107 | | ) public { 108 | * | if (a == b) { 109 | | string memory aStr = FuzzLibString.toString(a); 110 | | string memory bStr = FuzzLibString.toString(b); 111 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "==", reason); 112 | | emit AssertNeqFail(assertMsg); 113 | | platform.assertFail(); 114 | | } 115 | | } 116 | | 117 | | /// @notice int256 version of neq 118 | | function neq( 119 | | int256 a, 120 | | int256 b, 121 | | string memory reason 122 | | ) public { 123 | | if (a == b) { 124 | | string memory aStr = FuzzLibString.toString(a); 125 | | string memory bStr = FuzzLibString.toString(b); 126 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "==", reason); 127 | | emit AssertNeqFail(assertMsg); 128 | | platform.assertFail(); 129 | | } 130 | | } 131 | | 132 | | /// @notice asserts that a is greater than or equal to b. Violations are logged using reason. 133 | * | function gte( 134 | | uint256 a, 135 | | uint256 b, 136 | | string memory reason 137 | | ) public { 138 | * | if (!(a >= b)) { 139 | | string memory aStr = FuzzLibString.toString(a); 140 | | string memory bStr = FuzzLibString.toString(b); 141 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<", reason); 142 | | emit AssertGteFail(assertMsg); 143 | | platform.assertFail(); 144 | | } 145 | | } 146 | | 147 | | /// @notice int256 version of gte 148 | | function gte( 149 | | int256 a, 150 | | int256 b, 151 | | string memory reason 152 | | ) public { 153 | | if (!(a >= b)) { 154 | | string memory aStr = FuzzLibString.toString(a); 155 | | string memory bStr = FuzzLibString.toString(b); 156 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<", reason); 157 | | emit AssertGteFail(assertMsg); 158 | | platform.assertFail(); 159 | | } 160 | | } 161 | | 162 | | /// @notice asserts that a is greater than b. Violations are logged using reason. 163 | * | function gt( 164 | | uint256 a, 165 | | uint256 b, 166 | | string memory reason 167 | | ) public { 168 | * | if (!(a > b)) { 169 | | string memory aStr = FuzzLibString.toString(a); 170 | | string memory bStr = FuzzLibString.toString(b); 171 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<=", reason); 172 | | emit AssertGtFail(assertMsg); 173 | | platform.assertFail(); 174 | | } 175 | | } 176 | | 177 | | /// @notice int256 version of gt 178 | | function gt( 179 | | int256 a, 180 | | int256 b, 181 | | string memory reason 182 | | ) public { 183 | | if (!(a > b)) { 184 | | string memory aStr = FuzzLibString.toString(a); 185 | | string memory bStr = FuzzLibString.toString(b); 186 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, "<=", reason); 187 | | emit AssertGtFail(assertMsg); 188 | | platform.assertFail(); 189 | | } 190 | | } 191 | | 192 | | /// @notice asserts that a is less than or equal to b. Violations are logged using reason. 193 | * | function lte( 194 | | uint256 a, 195 | | uint256 b, 196 | | string memory reason 197 | | ) public { 198 | * | if (!(a <= b)) { 199 | | string memory aStr = FuzzLibString.toString(a); 200 | | string memory bStr = FuzzLibString.toString(b); 201 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">", reason); 202 | | emit AssertLteFail(assertMsg); 203 | | platform.assertFail(); 204 | | } 205 | | } 206 | | 207 | | /// @notice int256 version of lte 208 | | function lte( 209 | | int256 a, 210 | | int256 b, 211 | | string memory reason 212 | | ) public { 213 | | if (!(a <= b)) { 214 | | string memory aStr = FuzzLibString.toString(a); 215 | | string memory bStr = FuzzLibString.toString(b); 216 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">", reason); 217 | | emit AssertLteFail(assertMsg); 218 | | platform.assertFail(); 219 | | } 220 | | } 221 | | 222 | | /// @notice asserts that a is less than b. Violations are logged using reason. 223 | * | function lt( 224 | | uint256 a, 225 | | uint256 b, 226 | | string memory reason 227 | | ) public { 228 | * | if (!(a < b)) { 229 | | string memory aStr = FuzzLibString.toString(a); 230 | | string memory bStr = FuzzLibString.toString(b); 231 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">=", reason); 232 | | emit AssertLtFail(assertMsg); 233 | | platform.assertFail(); 234 | | } 235 | | } 236 | | 237 | | /// @notice int256 version of lt 238 | | function lt( 239 | | int256 a, 240 | | int256 b, 241 | | string memory reason 242 | | ) public { 243 | | if (!(a < b)) { 244 | | string memory aStr = FuzzLibString.toString(a); 245 | | string memory bStr = FuzzLibString.toString(b); 246 | | string memory assertMsg = createAssertFailMessage(aStr, bStr, ">=", reason); 247 | | emit AssertLtFail(assertMsg); 248 | | platform.assertFail(); 249 | | } 250 | | } 251 | | 252 | | function assertRevertReasonNotEqual( 253 | | bytes memory returnData, 254 | | string memory reason 255 | | ) public { 256 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); 257 | | t(!isEqual, reason); 258 | | } 259 | | 260 | | function assertRevertReasonEqual( 261 | | bytes memory returnData, 262 | | string memory reason 263 | | ) public { 264 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason); 265 | | t(isEqual, reason); 266 | | } 267 | | 268 | | function assertRevertReasonEqual( 269 | | bytes memory returnData, 270 | | string memory reason1, 271 | | string memory reason2 272 | | ) public { 273 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || 274 | | FuzzLibString.isRevertReasonEqual(returnData, reason2); 275 | | string memory assertMsg = string( 276 | | abi.encodePacked(reason1, " OR ", reason2) 277 | | ); 278 | | t(isEqual, assertMsg); 279 | | } 280 | | 281 | | function assertRevertReasonEqual( 282 | | bytes memory returnData, 283 | | string memory reason1, 284 | | string memory reason2, 285 | | string memory reason3 286 | | ) public { 287 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || 288 | | FuzzLibString.isRevertReasonEqual(returnData, reason2) || 289 | | FuzzLibString.isRevertReasonEqual(returnData, reason3); 290 | | string memory assertMsg = string( 291 | | abi.encodePacked(reason1, " OR ", reason2, " OR ", reason3) 292 | | ); 293 | | t(isEqual, assertMsg); 294 | | } 295 | | 296 | | function assertRevertReasonEqual( 297 | | bytes memory returnData, 298 | | string memory reason1, 299 | | string memory reason2, 300 | | string memory reason3, 301 | | string memory reason4 302 | | ) public { 303 | | bool isEqual = FuzzLibString.isRevertReasonEqual(returnData, reason1) || 304 | | FuzzLibString.isRevertReasonEqual(returnData, reason2) || 305 | | FuzzLibString.isRevertReasonEqual(returnData, reason3) || 306 | | FuzzLibString.isRevertReasonEqual(returnData, reason4); 307 | | string memory assertMsg = string( 308 | | abi.encodePacked( 309 | | reason1, 310 | | " OR ", 311 | | reason2, 312 | | " OR ", 313 | | reason3, 314 | | " OR ", 315 | | reason4 316 | | ) 317 | | ); 318 | | t(isEqual, assertMsg); 319 | | } 320 | | 321 | | function errAllow( 322 | | bytes4 errorSelector, 323 | | bytes4[] memory allowedErrors, 324 | | string memory message 325 | | ) public { 326 | | bool allowed = false; 327 | | for (uint256 i = 0; i < allowedErrors.length; i++) { 328 | | if (errorSelector == allowedErrors[i]) { 329 | | allowed = true; 330 | | break; 331 | | } 332 | | } 333 | | t(allowed, message); 334 | | } 335 | | 336 | | function errsAllow( 337 | | bytes4 errorSelector, 338 | | bytes4[] memory allowedErrors, 339 | | string[] memory messages 340 | | ) public { 341 | | bool allowed = false; 342 | | uint256 passIndex = 0; 343 | | for (uint256 i = 0; i < allowedErrors.length; i++) { 344 | | if (errorSelector == allowedErrors[i]) { 345 | | allowed = true; 346 | | passIndex = i; 347 | | break; 348 | | } 349 | | } 350 | | t(allowed, messages[passIndex]); 351 | | } 352 | | 353 | | function createAssertFailMessage(string memory aStr, string memory bStr, string memory operator, string memory reason)internal pure returns (string memory) { 354 | | return string(abi.encodePacked("Invalid: ", aStr, operator, bStr, ", reason: ", reason)); 355 | | } 356 | | 357 | | } 358 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperBase.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {IPlatform} from "../platform/IPlatform.sol"; 5 | | 6 | | contract HelperBase { 7 | | IPlatform public platform; 8 | | 9 | | function setPlatform(address _platform) public { 10 | | platform = IPlatform(_platform); 11 | | } 12 | | } 13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperClamp.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "../FuzzLibString.sol"; 5 | | import "./HelperAssert.sol"; 6 | | 7 | | /// @author Based on Crytic PropertiesHelper (https://github.com/crytic/properties/blob/main/contracts/util/PropertiesHelper.sol) 8 | | abstract contract HelperClamp is HelperAssert { 9 | | event Clamped(string); 10 | | 11 | | /* 12 | | ************************************************************************** 13 | | * Clamp functions with logging enabled 14 | | ************************************************************************** 15 | | */ 16 | | 17 | | /// @notice Clamps value to be between low and high, both inclusive 18 | * | function clamp( 19 | | uint256 value, 20 | | uint256 low, 21 | | uint256 high 22 | * | ) public returns (uint256) { 23 | * | return clamp(value, low, high, true); 24 | | } 25 | | 26 | | /// @notice int256 version of clamp 27 | | function clamp( 28 | | int256 value, 29 | | int256 low, 30 | | int256 high 31 | | ) public returns (int256) { 32 | | return clamp(value, low, high, true); 33 | | } 34 | | 35 | | /// @notice clamps a to be less than b 36 | | function clampLt(uint256 a, uint256 b) public returns (uint256) { 37 | | return clampLt(a, b); 38 | | } 39 | | 40 | | /// @notice int256 version of clampLt 41 | | function clampLt(int256 a, int256 b) public returns (int256) { 42 | | return clampLt(a, b, true); 43 | | } 44 | | 45 | | /// @notice clamps a to be less than or equal to b 46 | | function clampLte(uint256 a, uint256 b) public returns (uint256) { 47 | | return clampLte(a, b, true); 48 | | } 49 | | 50 | | /// @notice int256 version of clampLte 51 | | function clampLte(int256 a, int256 b) public returns (int256) { 52 | | return clampLte(a, b, true); 53 | | } 54 | | 55 | | /// @notice clamps a to be greater than b 56 | | function clampGt(uint256 a, uint256 b) public returns (uint256) { 57 | | return clampGt(a, b, true); 58 | | } 59 | | 60 | | /// @notice int256 version of clampGt 61 | | function clampGt(int256 a, int256 b) public returns (int256) { 62 | | return clampGt(a, b, true); 63 | | } 64 | | 65 | | /// @notice clamps a to be greater than or equal to b 66 | | function clampGte(uint256 a, uint256 b) public returns (uint256) { 67 | | return clampGte(a, b, true); 68 | | } 69 | | 70 | | /// @notice int256 version of clampGte 71 | | function clampGte(int256 a, int256 b) public returns (int256) { 72 | | return clampGte(a, b, true); 73 | | } 74 | | 75 | | /* 76 | | ************************************************************************** 77 | | * Clamp functions with optional logging 78 | | ************************************************************************** 79 | | */ 80 | | 81 | | /// @notice Clamps value to be between low and high, both inclusive 82 | * | function clamp( 83 | | uint256 value, 84 | | uint256 low, 85 | | uint256 high, 86 | | bool enableLogs 87 | * | ) public returns (uint256) { 88 | * | if (value < low || value > high) { 89 | * | uint256 ans = low + (value % (high - low + 1)); 90 | * | if (enableLogs) { 91 | * | string memory valueStr = FuzzLibString.toString(value); 92 | * | string memory ansStr = FuzzLibString.toString(ans); 93 | * | bytes memory message = abi.encodePacked( 94 | | "Clamping value ", 95 | * | valueStr, 96 | | " to ", 97 | * | ansStr 98 | | ); 99 | * | emit Clamped(string(message)); 100 | | } 101 | * | return ans; 102 | | } 103 | * | return value; 104 | | } 105 | | 106 | | /// @notice int256 version of clamp 107 | | function clamp( 108 | | int256 value, 109 | | int256 low, 110 | | int256 high, 111 | | bool enableLogs 112 | | ) public returns (int256) { 113 | | if (value < low || value > high) { 114 | | int256 range = high - low + 1; 115 | | int256 clamped = (value - low) % (range); 116 | | if (clamped < 0) clamped += range; 117 | | int256 ans = low + clamped; 118 | | if (enableLogs) { 119 | | string memory valueStr = FuzzLibString.toString(value); 120 | | string memory ansStr = FuzzLibString.toString(ans); 121 | | bytes memory message = abi.encodePacked( 122 | | "Clamping value ", 123 | | valueStr, 124 | | " to ", 125 | | ansStr 126 | | ); 127 | | emit Clamped(string(message)); 128 | | } 129 | | return ans; 130 | | } 131 | | return value; 132 | | } 133 | | 134 | | /// @notice clamps a to be less than b 135 | | function clampLt( 136 | | uint256 a, 137 | | uint256 b, 138 | | bool enableLogs 139 | | ) public returns (uint256) { 140 | | if (!(a < b)) { 141 | | neq( 142 | | b, 143 | | 0, 144 | | "clampLt cannot clamp value a to be less than zero. Check your inputs/assumptions." 145 | | ); 146 | | uint256 value = a % b; 147 | | if (enableLogs) { 148 | | string memory aStr = FuzzLibString.toString(a); 149 | | string memory valueStr = FuzzLibString.toString(value); 150 | | bytes memory message = abi.encodePacked( 151 | | "Clamping value ", 152 | | aStr, 153 | | " to ", 154 | | valueStr 155 | | ); 156 | | emit Clamped(string(message)); 157 | | } 158 | | return value; 159 | | } 160 | | return a; 161 | | } 162 | | 163 | | /// @notice int256 version of clampLt 164 | | function clampLt( 165 | | int256 a, 166 | | int256 b, 167 | | bool enableLogs 168 | | ) public returns (int256) { 169 | | if (!(a < b)) { 170 | | int256 value = b - 1; 171 | | if (enableLogs) { 172 | | string memory aStr = FuzzLibString.toString(a); 173 | | string memory valueStr = FuzzLibString.toString(value); 174 | | bytes memory message = abi.encodePacked( 175 | | "Clamping value ", 176 | | aStr, 177 | | " to ", 178 | | valueStr 179 | | ); 180 | | emit Clamped(string(message)); 181 | | } 182 | | return value; 183 | | } 184 | | return a; 185 | | } 186 | | 187 | | /// @notice clamps a to be less than or equal to b 188 | | function clampLte( 189 | | uint256 a, 190 | | uint256 b, 191 | | bool enableLogs 192 | | ) public returns (uint256) { 193 | | if (!(a <= b)) { 194 | | uint256 value = a % (b + 1); 195 | | if (enableLogs) { 196 | | string memory aStr = FuzzLibString.toString(a); 197 | | string memory valueStr = FuzzLibString.toString(value); 198 | | bytes memory message = abi.encodePacked( 199 | | "Clamping value ", 200 | | aStr, 201 | | " to ", 202 | | valueStr 203 | | ); 204 | | emit Clamped(string(message)); 205 | | } 206 | | return value; 207 | | } 208 | | return a; 209 | | } 210 | | 211 | | /// @notice int256 version of clampLte 212 | | function clampLte( 213 | | int256 a, 214 | | int256 b, 215 | | bool enableLogs 216 | | ) public returns (int256) { 217 | | if (!(a <= b)) { 218 | | int256 value = b; 219 | | if (enableLogs) { 220 | | string memory aStr = FuzzLibString.toString(a); 221 | | string memory valueStr = FuzzLibString.toString(value); 222 | | bytes memory message = abi.encodePacked( 223 | | "Clamping value ", 224 | | aStr, 225 | | " to ", 226 | | valueStr 227 | | ); 228 | | emit Clamped(string(message)); 229 | | } 230 | | return value; 231 | | } 232 | | return a; 233 | | } 234 | | 235 | | /// @notice clamps a to be greater than b 236 | | function clampGt( 237 | | uint256 a, 238 | | uint256 b, 239 | | bool enableLogs 240 | | ) public returns (uint256) { 241 | | if (!(a > b)) { 242 | | neq( 243 | | b, 244 | | type(uint256).max, 245 | | "clampGt cannot clamp value a to be larger than uint256.max. Check your inputs/assumptions." 246 | | ); 247 | | uint256 value = b + 1; 248 | | if (enableLogs) { 249 | | string memory aStr = FuzzLibString.toString(a); 250 | | string memory valueStr = FuzzLibString.toString(value); 251 | | bytes memory message = abi.encodePacked( 252 | | "Clamping value ", 253 | | aStr, 254 | | " to ", 255 | | valueStr 256 | | ); 257 | | emit Clamped(string(message)); 258 | | } 259 | | return value; 260 | | } else { 261 | | return a; 262 | | } 263 | | } 264 | | 265 | | /// @notice int256 version of clampGt 266 | | function clampGt( 267 | | int256 a, 268 | | int256 b, 269 | | bool enableLogs 270 | | ) public returns (int256) { 271 | | if (!(a > b)) { 272 | | int256 value = b + 1; 273 | | if (enableLogs) { 274 | | string memory aStr = FuzzLibString.toString(a); 275 | | string memory valueStr = FuzzLibString.toString(value); 276 | | bytes memory message = abi.encodePacked( 277 | | "Clamping value ", 278 | | aStr, 279 | | " to ", 280 | | valueStr 281 | | ); 282 | | emit Clamped(string(message)); 283 | | } 284 | | return value; 285 | | } else { 286 | | return a; 287 | | } 288 | | } 289 | | 290 | | /// @notice clamps a to be greater than or equal to b 291 | | function clampGte( 292 | | uint256 a, 293 | | uint256 b, 294 | | bool enableLogs 295 | | ) public returns (uint256) { 296 | | if (!(a > b)) { 297 | | uint256 value = b; 298 | | if (enableLogs) { 299 | | string memory aStr = FuzzLibString.toString(a); 300 | | string memory valueStr = FuzzLibString.toString(value); 301 | | bytes memory message = abi.encodePacked( 302 | | "Clamping value ", 303 | | aStr, 304 | | " to ", 305 | | valueStr 306 | | ); 307 | | emit Clamped(string(message)); 308 | | } 309 | | return value; 310 | | } 311 | | return a; 312 | | } 313 | | 314 | | /// @notice int256 version of clampGte 315 | | function clampGte( 316 | | int256 a, 317 | | int256 b, 318 | | bool enableLogs 319 | | ) public returns (int256) { 320 | | if (!(a > b)) { 321 | | int256 value = b; 322 | | if (enableLogs) { 323 | | string memory aStr = FuzzLibString.toString(a); 324 | | string memory valueStr = FuzzLibString.toString(value); 325 | | bytes memory message = abi.encodePacked( 326 | | "Clamping value ", 327 | | aStr, 328 | | " to ", 329 | | valueStr 330 | | ); 331 | | emit Clamped(string(message)); 332 | | } 333 | | return value; 334 | | } 335 | | return a; 336 | | } 337 | | } 338 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperLog.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {LibLog} from "../libraries/LibLog.sol"; 5 | | 6 | | abstract contract HelperLog { 7 | * | function log(string memory message) public { 8 | * | LibLog.log(message); 9 | | } 10 | | 11 | | function log(string memory message, string memory data) public { 12 | | LibLog.log(message, data); 13 | | } 14 | | 15 | | function log(string memory message, bytes memory data) public { 16 | | LibLog.log(message, data); 17 | | } 18 | | 19 | * | function log(string memory message, uint256 data) public { 20 | * | LibLog.log(message, data); 21 | | } 22 | | 23 | | function log(string memory message, int256 data) public { 24 | | LibLog.log(message, data); 25 | | } 26 | | 27 | | function log(string memory message, address data) public { 28 | | LibLog.log(message, data); 29 | | } 30 | | 31 | | function log(string memory message, bool data) public { 32 | | LibLog.log(message, data); 33 | | } 34 | | 35 | | function log(string memory message, bytes32 data) public { 36 | | LibLog.log(message, data); 37 | | } 38 | | 39 | | function logFail() public { 40 | | LibLog.logFail(); 41 | | } 42 | | 43 | | function logFail(string memory message) public { 44 | | LibLog.logFail(message); 45 | | } 46 | | 47 | | function logFail(string memory message, string memory data) public { 48 | | LibLog.logFail(message, data); 49 | | } 50 | | 51 | | function logFail(string memory message, bytes memory data) public { 52 | | LibLog.logFail(message, data); 53 | | } 54 | | 55 | | function logFail(string memory message, uint256 data) public { 56 | | LibLog.logFail(message, data); 57 | | } 58 | | 59 | | function logFail(string memory message, int256 data) public { 60 | | LibLog.logFail(message, data); 61 | | } 62 | | 63 | | function logFail(string memory message, address data) public { 64 | | LibLog.logFail(message, data); 65 | | } 66 | | 67 | | function logFail(string memory message, bool data) public { 68 | | LibLog.logFail(message, data); 69 | | } 70 | | 71 | | function logFail(string memory message, bytes32 data) public { 72 | | LibLog.log(message, data); 73 | | } 74 | | } 75 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperMath.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | abstract contract HelperMath { 5 | | function min(uint256 a, uint256 b) public pure returns (uint256) { 6 | | return a < b ? a : b; 7 | | } 8 | | 9 | | function max(uint256 a, uint256 b) public pure returns (uint256) { 10 | | return a > b ? a : b; 11 | | } 12 | | 13 | | // Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/utils/math/SignedMath.sol 14 | | function max(int256 a, int256 b) public pure returns (int256) { 15 | | return a > b ? a : b; 16 | | } 17 | | 18 | | // Forked with modifications from https://ethereum.stackexchange.com/a/84391 19 | | function abs(int128 n) public pure returns (int128) { 20 | | return n >= 0 ? n : -n; 21 | | } 22 | | 23 | | function abs(int256 n) public pure returns (uint256) { 24 | | return n >= 0 ? uint256(n) : uint256(-n); 25 | | } 26 | | 27 | | function diff(int256 a, int256 b) public pure returns (uint256) { 28 | | return a >= b ? uint256(a - b) : uint256(b - a); 29 | | } 30 | | 31 | | function diff(uint256 a, uint256 b) public pure returns (uint256) { 32 | | return a >= b ? a - b : b - a; 33 | | } 34 | | } 35 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/helpers/HelperRandom.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | abstract contract HelperRandom { 5 | | /// @notice Shuffle an array using Fisher-Yates algorithm 6 | | /// @dev Based on https://gist.github.com/scammi/602387a22e04c77beb73c0ebc0f0bc18 7 | | function shuffleArray( 8 | | uint256[] memory shuffle, 9 | | uint256 entropy 10 | | ) public pure { 11 | | for (uint256 i = shuffle.length - 1; i > 0; i--) { 12 | | uint256 swapIndex = entropy % (shuffle.length - i); 13 | | 14 | | uint256 currentIndex = shuffle[i]; 15 | | uint256 indexToSwap = shuffle[swapIndex]; 16 | | 17 | | shuffle[i] = indexToSwap; 18 | | shuffle[swapIndex] = currentIndex; 19 | | } 20 | | } 21 | | } 22 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/libraries/LibLog.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | * | library LibLog { 5 | | event Log(string message); 6 | | event LogString(string message, string data); 7 | | event LogBytes(string message, bytes data); 8 | | event LogUint(string message, uint256 data); 9 | | event LogInt(string message, int256 data); 10 | | event LogAddress(string message, address data); 11 | | event LogBool(string message, bool data); 12 | | event LogBytes32(string message, bytes32 data); 13 | | 14 | | event AssertionFailed(); 15 | | event AssertionFailed(string message); 16 | | event AssertionFailed(string message, string data); 17 | | event AssertionFailed(string message, bytes data); 18 | | event AssertionFailed(string message, uint256 data); 19 | | event AssertionFailed(string message, int256 data); 20 | | event AssertionFailed(string message, address data); 21 | | event AssertionFailed(string message, bool data); 22 | | 23 | * | function log(string memory message) internal { 24 | * | emit Log(message); 25 | | } 26 | | 27 | | function log(string memory message, string memory data) internal { 28 | | emit LogString(message, data); 29 | | } 30 | | 31 | | function log(string memory message, bytes memory data) internal { 32 | | emit LogBytes(message, data); 33 | | } 34 | | 35 | * | function log(string memory message, uint256 data) internal { 36 | * | emit LogUint(message, data); 37 | | } 38 | | 39 | | function log(string memory message, int256 data) internal { 40 | | emit LogInt(message, data); 41 | | } 42 | | 43 | | function log(string memory message, address data) internal { 44 | | emit LogAddress(message, data); 45 | | } 46 | | 47 | | function log(string memory message, bool data) internal { 48 | | emit LogBool(message, data); 49 | | } 50 | | 51 | | function log(string memory message, bytes32 data) internal { 52 | | emit LogBytes32(message, data); 53 | | } 54 | | 55 | | function logFail() internal { 56 | | emit AssertionFailed(); 57 | | } 58 | | 59 | | function logFail(string memory message) internal { 60 | | emit AssertionFailed(message); 61 | | } 62 | | 63 | | function logFail(string memory message, string memory data) internal { 64 | | emit AssertionFailed(message, data); 65 | | } 66 | | 67 | | function logFail(string memory message, bytes memory data) internal { 68 | | emit AssertionFailed(message, data); 69 | | } 70 | | 71 | | function logFail(string memory message, uint256 data) internal { 72 | | emit AssertionFailed(message, data); 73 | | } 74 | | 75 | | function logFail(string memory message, int256 data) internal { 76 | | emit AssertionFailed(message, data); 77 | | } 78 | | 79 | | function logFail(string memory message, address data) internal { 80 | | emit AssertionFailed(message, data); 81 | | } 82 | | 83 | | function logFail(string memory message, bool data) internal { 84 | | emit AssertionFailed(message, data); 85 | | } 86 | | 87 | | function logFail(string memory message, bytes32 data) internal { 88 | | emit LogBytes32(message, data); 89 | | } 90 | | } 91 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/platform/IPlatform.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | interface IPlatform { 5 | | function assertFail() pure external; 6 | | } 7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/lib/fuzzlib/src/platform/PlatformCrytic.sol 1 | | 2 | | // SPDX-License-Identifier: MIT 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import {IPlatform} from "./IPlatform.sol"; 6 | | 7 | * | contract PlatformCrytic is IPlatform { 8 | * | function assertFail() pure public override{ 9 | * | assert(false); 10 | | } 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorInterface.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | // solhint-disable-next-line interface-starts-with-i 5 | | interface AggregatorInterface { 6 | | function latestAnswer() external view returns (int256); 7 | | 8 | | function latestTimestamp() external view returns (uint256); 9 | | 10 | | function latestRound() external view returns (uint256); 11 | | 12 | | function getAnswer(uint256 roundId) external view returns (int256); 13 | | 14 | | function getTimestamp(uint256 roundId) external view returns (uint256); 15 | | 16 | | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); 17 | | 18 | | event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); 19 | | } 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import {AggregatorInterface} from "./AggregatorInterface.sol"; 5 | | import {AggregatorV3Interface} from "./AggregatorV3Interface.sol"; 6 | | 7 | | // solhint-disable-next-line interface-starts-with-i 8 | | interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} 9 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | // solhint-disable-next-line interface-starts-with-i 5 | | interface AggregatorV3Interface { 6 | | function decimals() external view returns (uint8); 7 | | 8 | | function description() external view returns (string memory); 9 | | 10 | | function version() external view returns (uint256); 11 | | 12 | | function getRoundData( 13 | | uint80 _roundId 14 | | ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); 15 | | 16 | | function latestRoundData() 17 | | external 18 | | view 19 | | returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); 20 | | } 21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./OwnableUpgradeable.sol"; 7 | | import "../proxy/utils/Initializable.sol"; 8 | | 9 | | /** 10 | | * @dev Contract module which provides access control mechanism, where 11 | | * there is an account (an owner) that can be granted exclusive access to 12 | | * specific functions. 13 | | * 14 | | * By default, the owner account will be the one that deploys the contract. This 15 | | * can later be changed with {transferOwnership} and {acceptOwnership}. 16 | | * 17 | | * This module is used through inheritance. It will make available all functions 18 | | * from parent (Ownable). 19 | | */ 20 | | abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { 21 | | function __Ownable2Step_init() internal onlyInitializing { 22 | | __Ownable_init_unchained(); 23 | | } 24 | | 25 | | function __Ownable2Step_init_unchained() internal onlyInitializing { 26 | | } 27 | | address private _pendingOwner; 28 | | 29 | | event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); 30 | | 31 | | /** 32 | | * @dev Returns the address of the pending owner. 33 | | */ 34 | | function pendingOwner() public view virtual returns (address) { 35 | | return _pendingOwner; 36 | | } 37 | | 38 | | /** 39 | | * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. 40 | | * Can only be called by the current owner. 41 | | */ 42 | | function transferOwnership(address newOwner) public virtual override onlyOwner { 43 | | _pendingOwner = newOwner; 44 | | emit OwnershipTransferStarted(owner(), newOwner); 45 | | } 46 | | 47 | | /** 48 | | * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. 49 | | * Internal function without access restriction. 50 | | */ 51 | | function _transferOwnership(address newOwner) internal virtual override { 52 | | delete _pendingOwner; 53 | | super._transferOwnership(newOwner); 54 | | } 55 | | 56 | | /** 57 | | * @dev The new owner accepts the ownership transfer. 58 | | */ 59 | | function acceptOwnership() external { 60 | | address sender = _msgSender(); 61 | | require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); 62 | | _transferOwnership(sender); 63 | | } 64 | | 65 | | /** 66 | | * @dev This empty reserved space is put in place to allow future versions to add new 67 | | * variables without shifting down storage in the inheritance chain. 68 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps 69 | | */ 70 | | uint256[49] private __gap; 71 | | } 72 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../utils/ContextUpgradeable.sol"; 7 | | import "../proxy/utils/Initializable.sol"; 8 | | 9 | | /** 10 | | * @dev Contract module which provides a basic access control mechanism, where 11 | | * there is an account (an owner) that can be granted exclusive access to 12 | | * specific functions. 13 | | * 14 | | * By default, the owner account will be the one that deploys the contract. This 15 | | * can later be changed with {transferOwnership}. 16 | | * 17 | | * This module is used through inheritance. It will make available the modifier 18 | | * `onlyOwner`, which can be applied to your functions to restrict their use to 19 | | * the owner. 20 | | */ 21 | | abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { 22 | | address private _owner; 23 | | 24 | | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 25 | | 26 | | /** 27 | | * @dev Initializes the contract setting the deployer as the initial owner. 28 | | */ 29 | | function __Ownable_init() internal onlyInitializing { 30 | | __Ownable_init_unchained(); 31 | | } 32 | | 33 | | function __Ownable_init_unchained() internal onlyInitializing { 34 | | _transferOwnership(_msgSender()); 35 | | } 36 | | 37 | | /** 38 | | * @dev Throws if called by any account other than the owner. 39 | | */ 40 | | modifier onlyOwner() { 41 | | _checkOwner(); 42 | | _; 43 | | } 44 | | 45 | | /** 46 | | * @dev Returns the address of the current owner. 47 | | */ 48 | | function owner() public view virtual returns (address) { 49 | | return _owner; 50 | | } 51 | | 52 | | /** 53 | | * @dev Throws if the sender is not the owner. 54 | | */ 55 | | function _checkOwner() internal view virtual { 56 | | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 57 | | } 58 | | 59 | | /** 60 | | * @dev Leaves the contract without owner. It will not be possible to call 61 | | * `onlyOwner` functions anymore. Can only be called by the current owner. 62 | | * 63 | | * NOTE: Renouncing ownership will leave the contract without an owner, 64 | | * thereby removing any functionality that is only available to the owner. 65 | | */ 66 | | function renounceOwnership() public virtual onlyOwner { 67 | | _transferOwnership(address(0)); 68 | | } 69 | | 70 | | /** 71 | | * @dev Transfers ownership of the contract to a new account (`newOwner`). 72 | | * Can only be called by the current owner. 73 | | */ 74 | | function transferOwnership(address newOwner) public virtual onlyOwner { 75 | | require(newOwner != address(0), "Ownable: new owner is the zero address"); 76 | | _transferOwnership(newOwner); 77 | | } 78 | | 79 | | /** 80 | | * @dev Transfers ownership of the contract to a new account (`newOwner`). 81 | | * Internal function without access restriction. 82 | | */ 83 | | function _transferOwnership(address newOwner) internal virtual { 84 | | address oldOwner = _owner; 85 | | _owner = newOwner; 86 | | emit OwnershipTransferred(oldOwner, newOwner); 87 | | } 88 | | 89 | | /** 90 | | * @dev This empty reserved space is put in place to allow future versions to add new 91 | | * variables without shifting down storage in the inheritance chain. 92 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps 93 | | */ 94 | | uint256[49] private __gap; 95 | | } 96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol) 3 | | 4 | | pragma solidity ^0.8.2; 5 | | 6 | | import "../../utils/AddressUpgradeable.sol"; 7 | | 8 | | /** 9 | | * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed 10 | | * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an 11 | | * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer 12 | | * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. 13 | | * 14 | | * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be 15 | | * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in 16 | | * case an upgrade adds a module that needs to be initialized. 17 | | * 18 | | * For example: 19 | | * 20 | | * [.hljs-theme-light.nopadding] 21 | | * ``` 22 | | * contract MyToken is ERC20Upgradeable { 23 | | * function initialize() initializer public { 24 | | * __ERC20_init("MyToken", "MTK"); 25 | | * } 26 | | * } 27 | | * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { 28 | | * function initializeV2() reinitializer(2) public { 29 | | * __ERC20Permit_init("MyToken"); 30 | | * } 31 | | * } 32 | | * ``` 33 | | * 34 | | * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as 35 | | * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. 36 | | * 37 | | * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure 38 | | * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. 39 | | * 40 | | * [CAUTION] 41 | | * ==== 42 | | * Avoid leaving a contract uninitialized. 43 | | * 44 | | * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation 45 | | * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke 46 | | * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: 47 | | * 48 | | * [.hljs-theme-light.nopadding] 49 | | * ``` 50 | | * /// @custom:oz-upgrades-unsafe-allow constructor 51 | | * constructor() { 52 | | * _disableInitializers(); 53 | | * } 54 | | * ``` 55 | | * ==== 56 | | */ 57 | | abstract contract Initializable { 58 | | /** 59 | | * @dev Indicates that the contract has been initialized. 60 | | * @custom:oz-retyped-from bool 61 | | */ 62 | | uint8 private _initialized; 63 | | 64 | | /** 65 | | * @dev Indicates that the contract is in the process of being initialized. 66 | | */ 67 | | bool private _initializing; 68 | | 69 | | /** 70 | | * @dev Triggered when the contract has been initialized or reinitialized. 71 | | */ 72 | | event Initialized(uint8 version); 73 | | 74 | | /** 75 | | * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, 76 | | * `onlyInitializing` functions can be used to initialize parent contracts. 77 | | * 78 | | * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a 79 | | * constructor. 80 | | * 81 | | * Emits an {Initialized} event. 82 | | */ 83 | | modifier initializer() { 84 | | bool isTopLevelCall = !_initializing; 85 | | require( 86 | | (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), 87 | | "Initializable: contract is already initialized" 88 | | ); 89 | | _initialized = 1; 90 | | if (isTopLevelCall) { 91 | | _initializing = true; 92 | | } 93 | | _; 94 | | if (isTopLevelCall) { 95 | | _initializing = false; 96 | | emit Initialized(1); 97 | | } 98 | | } 99 | | 100 | | /** 101 | | * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the 102 | | * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be 103 | | * used to initialize parent contracts. 104 | | * 105 | | * A reinitializer may be used after the original initialization step. This is essential to configure modules that 106 | | * are added through upgrades and that require initialization. 107 | | * 108 | | * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` 109 | | * cannot be nested. If one is invoked in the context of another, execution will revert. 110 | | * 111 | | * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in 112 | | * a contract, executing them in the right order is up to the developer or operator. 113 | | * 114 | | * WARNING: setting the version to 255 will prevent any future reinitialization. 115 | | * 116 | | * Emits an {Initialized} event. 117 | | */ 118 | | modifier reinitializer(uint8 version) { 119 | | require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); 120 | | _initialized = version; 121 | | _initializing = true; 122 | | _; 123 | | _initializing = false; 124 | | emit Initialized(version); 125 | | } 126 | | 127 | | /** 128 | | * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the 129 | | * {initializer} and {reinitializer} modifiers, directly or indirectly. 130 | | */ 131 | | modifier onlyInitializing() { 132 | | require(_initializing, "Initializable: contract is not initializing"); 133 | | _; 134 | | } 135 | | 136 | | /** 137 | | * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. 138 | | * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized 139 | | * to any version. It is recommended to use this to lock implementation contracts that are designed to be called 140 | | * through proxies. 141 | | * 142 | | * Emits an {Initialized} event the first time it is successfully executed. 143 | | */ 144 | | function _disableInitializers() internal virtual { 145 | | require(!_initializing, "Initializable: contract is initializing"); 146 | | if (_initialized < type(uint8).max) { 147 | | _initialized = type(uint8).max; 148 | | emit Initialized(type(uint8).max); 149 | | } 150 | | } 151 | | 152 | | /** 153 | | * @dev Returns the highest version that has been initialized. See {reinitializer}. 154 | | */ 155 | | function _getInitializedVersion() internal view returns (uint8) { 156 | | return _initialized; 157 | | } 158 | | 159 | | /** 160 | | * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. 161 | | */ 162 | | function _isInitializing() internal view returns (bool) { 163 | | return _initializing; 164 | | } 165 | | } 166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | import "../proxy/utils/Initializable.sol"; 6 | | 7 | | /** 8 | | * @dev Contract module that helps prevent reentrant calls to a function. 9 | | * 10 | | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 11 | | * available, which can be applied to functions to make sure there are no nested 12 | | * (reentrant) calls to them. 13 | | * 14 | | * Note that because there is a single `nonReentrant` guard, functions marked as 15 | | * `nonReentrant` may not call one another. This can be worked around by making 16 | | * those functions `private`, and then adding `external` `nonReentrant` entry 17 | | * points to them. 18 | | * 19 | | * TIP: If you would like to learn more about reentrancy and alternative ways 20 | | * to protect against it, check out our blog post 21 | | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. 22 | | */ 23 | | abstract contract ReentrancyGuardUpgradeable is Initializable { 24 | | // Booleans are more expensive than uint256 or any type that takes up a full 25 | | // word because each write operation emits an extra SLOAD to first read the 26 | | // slot's contents, replace the bits taken up by the boolean, and then write 27 | | // back. This is the compiler's defense against contract upgrades and 28 | | // pointer aliasing, and it cannot be disabled. 29 | | 30 | | // The values being non-zero value makes deployment a bit more expensive, 31 | | // but in exchange the refund on every call to nonReentrant will be lower in 32 | | // amount. Since refunds are capped to a percentage of the total 33 | | // transaction's gas, it is best to keep them low in cases like this one, to 34 | | // increase the likelihood of the full refund coming into effect. 35 | * | uint256 private constant _NOT_ENTERED = 1; 36 | * | uint256 private constant _ENTERED = 2; 37 | | 38 | | uint256 private _status; 39 | | 40 | | function __ReentrancyGuard_init() internal onlyInitializing { 41 | | __ReentrancyGuard_init_unchained(); 42 | | } 43 | | 44 | | function __ReentrancyGuard_init_unchained() internal onlyInitializing { 45 | | _status = _NOT_ENTERED; 46 | | } 47 | | 48 | | /** 49 | | * @dev Prevents a contract from calling itself, directly or indirectly. 50 | | * Calling a `nonReentrant` function from another `nonReentrant` 51 | | * function is not supported. It is possible to prevent this from happening 52 | | * by making the `nonReentrant` function external, and making it call a 53 | | * `private` function that does the actual work. 54 | | */ 55 | | modifier nonReentrant() { 56 | * | _nonReentrantBefore(); 57 | * | _; 58 | * | _nonReentrantAfter(); 59 | | } 60 | | 61 | * | function _nonReentrantBefore() private { 62 | | // On the first call to nonReentrant, _status will be _NOT_ENTERED 63 | * | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 64 | | 65 | | // Any calls to nonReentrant after this point will fail 66 | * | _status = _ENTERED; 67 | | } 68 | | 69 | * | function _nonReentrantAfter() private { 70 | | // By storing the original value once again, a refund is triggered (see 71 | | // https://eips.ethereum.org/EIPS/eip-2200) 72 | * | _status = _NOT_ENTERED; 73 | | } 74 | | 75 | | /** 76 | | * @dev This empty reserved space is put in place to allow future versions to add new 77 | | * variables without shifting down storage in the inheritance chain. 78 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps 79 | | */ 80 | | uint256[49] private __gap; 81 | | } 82 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) 3 | | 4 | | pragma solidity ^0.8.1; 5 | | 6 | | /** 7 | | * @dev Collection of functions related to the address type 8 | | */ 9 | * | library AddressUpgradeable { 10 | | /** 11 | | * @dev Returns true if `account` is a contract. 12 | | * 13 | | * [IMPORTANT] 14 | | * ==== 15 | | * It is unsafe to assume that an address for which this function returns 16 | | * false is an externally-owned account (EOA) and not a contract. 17 | | * 18 | | * Among others, `isContract` will return false for the following 19 | | * types of addresses: 20 | | * 21 | | * - an externally-owned account 22 | | * - a contract in construction 23 | | * - an address where a contract will be created 24 | | * - an address where a contract lived, but was destroyed 25 | | * ==== 26 | | * 27 | | * [IMPORTANT] 28 | | * ==== 29 | | * You shouldn't rely on `isContract` to protect against flash loan attacks! 30 | | * 31 | | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets 32 | | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract 33 | | * constructor. 34 | | * ==== 35 | | */ 36 | | function isContract(address account) internal view returns (bool) { 37 | | // This method relies on extcodesize/address.code.length, which returns 0 38 | | // for contracts in construction, since the code is only stored at the end 39 | | // of the constructor execution. 40 | | 41 | | return account.code.length > 0; 42 | | } 43 | | 44 | | /** 45 | | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 46 | | * `recipient`, forwarding all available gas and reverting on errors. 47 | | * 48 | | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 49 | | * of certain opcodes, possibly making contracts go over the 2300 gas limit 50 | | * imposed by `transfer`, making them unable to receive funds via 51 | | * `transfer`. {sendValue} removes this limitation. 52 | | * 53 | | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 54 | | * 55 | | * IMPORTANT: because control is transferred to `recipient`, care must be 56 | | * taken to not create reentrancy vulnerabilities. Consider using 57 | | * {ReentrancyGuard} or the 58 | | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 59 | | */ 60 | | function sendValue(address payable recipient, uint256 amount) internal { 61 | | require(address(this).balance >= amount, "Address: insufficient balance"); 62 | | 63 | | (bool success, ) = recipient.call{value: amount}(""); 64 | | require(success, "Address: unable to send value, recipient may have reverted"); 65 | | } 66 | | 67 | | /** 68 | | * @dev Performs a Solidity function call using a low level `call`. A 69 | | * plain `call` is an unsafe replacement for a function call: use this 70 | | * function instead. 71 | | * 72 | | * If `target` reverts with a revert reason, it is bubbled up by this 73 | | * function (like regular Solidity function calls). 74 | | * 75 | | * Returns the raw returned data. To convert to the expected return value, 76 | | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 77 | | * 78 | | * Requirements: 79 | | * 80 | | * - `target` must be a contract. 81 | | * - calling `target` with `data` must not revert. 82 | | * 83 | | * _Available since v3.1._ 84 | | */ 85 | | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 86 | | return functionCallWithValue(target, data, 0, "Address: low-level call failed"); 87 | | } 88 | | 89 | | /** 90 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 91 | | * `errorMessage` as a fallback revert reason when `target` reverts. 92 | | * 93 | | * _Available since v3.1._ 94 | | */ 95 | | function functionCall( 96 | | address target, 97 | | bytes memory data, 98 | | string memory errorMessage 99 | | ) internal returns (bytes memory) { 100 | | return functionCallWithValue(target, data, 0, errorMessage); 101 | | } 102 | | 103 | | /** 104 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 105 | | * but also transferring `value` wei to `target`. 106 | | * 107 | | * Requirements: 108 | | * 109 | | * - the calling contract must have an ETH balance of at least `value`. 110 | | * - the called Solidity function must be `payable`. 111 | | * 112 | | * _Available since v3.1._ 113 | | */ 114 | | function functionCallWithValue( 115 | | address target, 116 | | bytes memory data, 117 | | uint256 value 118 | | ) internal returns (bytes memory) { 119 | | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 120 | | } 121 | | 122 | | /** 123 | | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 124 | | * with `errorMessage` as a fallback revert reason when `target` reverts. 125 | | * 126 | | * _Available since v3.1._ 127 | | */ 128 | | function functionCallWithValue( 129 | | address target, 130 | | bytes memory data, 131 | | uint256 value, 132 | | string memory errorMessage 133 | | ) internal returns (bytes memory) { 134 | | require(address(this).balance >= value, "Address: insufficient balance for call"); 135 | | (bool success, bytes memory returndata) = target.call{value: value}(data); 136 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage); 137 | | } 138 | | 139 | | /** 140 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 141 | | * but performing a static call. 142 | | * 143 | | * _Available since v3.3._ 144 | | */ 145 | | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 146 | | return functionStaticCall(target, data, "Address: low-level static call failed"); 147 | | } 148 | | 149 | | /** 150 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 151 | | * but performing a static call. 152 | | * 153 | | * _Available since v3.3._ 154 | | */ 155 | | function functionStaticCall( 156 | | address target, 157 | | bytes memory data, 158 | | string memory errorMessage 159 | | ) internal view returns (bytes memory) { 160 | | (bool success, bytes memory returndata) = target.staticcall(data); 161 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage); 162 | | } 163 | | 164 | | /** 165 | | * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling 166 | | * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. 167 | | * 168 | | * _Available since v4.8._ 169 | | */ 170 | | function verifyCallResultFromTarget( 171 | | address target, 172 | | bool success, 173 | | bytes memory returndata, 174 | | string memory errorMessage 175 | | ) internal view returns (bytes memory) { 176 | | if (success) { 177 | | if (returndata.length == 0) { 178 | | // only check isContract if the call was successful and the return data is empty 179 | | // otherwise we already know that it was a contract 180 | | require(isContract(target), "Address: call to non-contract"); 181 | | } 182 | | return returndata; 183 | | } else { 184 | | _revert(returndata, errorMessage); 185 | | } 186 | | } 187 | | 188 | | /** 189 | | * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the 190 | | * revert reason or using the provided one. 191 | | * 192 | | * _Available since v4.3._ 193 | | */ 194 | | function verifyCallResult( 195 | | bool success, 196 | | bytes memory returndata, 197 | | string memory errorMessage 198 | | ) internal pure returns (bytes memory) { 199 | | if (success) { 200 | | return returndata; 201 | | } else { 202 | | _revert(returndata, errorMessage); 203 | | } 204 | | } 205 | | 206 | | function _revert(bytes memory returndata, string memory errorMessage) private pure { 207 | | // Look for revert reason and bubble it up if present 208 | | if (returndata.length > 0) { 209 | | // The easiest way to bubble the revert reason is using memory via assembly 210 | | /// @solidity memory-safe-assembly 211 | | assembly { 212 | | let returndata_size := mload(returndata) 213 | | revert(add(32, returndata), returndata_size) 214 | | } 215 | | } else { 216 | | revert(errorMessage); 217 | | } 218 | | } 219 | | } 220 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | import "../proxy/utils/Initializable.sol"; 6 | | 7 | | /** 8 | | * @dev Provides information about the current execution context, including the 9 | | * sender of the transaction and its data. While these are generally available 10 | | * via msg.sender and msg.data, they should not be accessed in such a direct 11 | | * manner, since when dealing with meta-transactions the account sending and 12 | | * paying for execution may not be the actual sender (as far as an application 13 | | * is concerned). 14 | | * 15 | | * This contract is only required for intermediate, library-like contracts. 16 | | */ 17 | | abstract contract ContextUpgradeable is Initializable { 18 | | function __Context_init() internal onlyInitializing { 19 | | } 20 | | 21 | | function __Context_init_unchained() internal onlyInitializing { 22 | | } 23 | | function _msgSender() internal view virtual returns (address) { 24 | | return msg.sender; 25 | | } 26 | | 27 | | function _msgData() internal view virtual returns (bytes calldata) { 28 | | return msg.data; 29 | | } 30 | | 31 | | /** 32 | | * @dev This empty reserved space is put in place to allow future versions to add new 33 | | * variables without shifting down storage in the inheritance chain. 34 | | * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps 35 | | */ 36 | | uint256[50] private __gap; 37 | | } 38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/AccessControl.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./IAccessControl.sol"; 7 | | import "../utils/Context.sol"; 8 | | import "../utils/Strings.sol"; 9 | | import "../utils/introspection/ERC165.sol"; 10 | | 11 | | /** 12 | | * @dev Contract module that allows children to implement role-based access 13 | | * control mechanisms. This is a lightweight version that doesn't allow enumerating role 14 | | * members except through off-chain means by accessing the contract event logs. Some 15 | | * applications may benefit from on-chain enumerability, for those cases see 16 | | * {AccessControlEnumerable}. 17 | | * 18 | | * Roles are referred to by their `bytes32` identifier. These should be exposed 19 | | * in the external API and be unique. The best way to achieve this is by 20 | | * using `public constant` hash digests: 21 | | * 22 | | * ```solidity 23 | | * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); 24 | | * ``` 25 | | * 26 | | * Roles can be used to represent a set of permissions. To restrict access to a 27 | | * function call, use {hasRole}: 28 | | * 29 | | * ```solidity 30 | | * function foo() public { 31 | | * require(hasRole(MY_ROLE, msg.sender)); 32 | | * ... 33 | | * } 34 | | * ``` 35 | | * 36 | | * Roles can be granted and revoked dynamically via the {grantRole} and 37 | | * {revokeRole} functions. Each role has an associated admin role, and only 38 | | * accounts that have a role's admin role can call {grantRole} and {revokeRole}. 39 | | * 40 | | * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means 41 | | * that only accounts with this role will be able to grant or revoke other 42 | | * roles. More complex role relationships can be created by using 43 | | * {_setRoleAdmin}. 44 | | * 45 | | * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to 46 | | * grant and revoke this role. Extra precautions should be taken to secure 47 | | * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} 48 | | * to enforce additional security measures for this role. 49 | | */ 50 | | abstract contract AccessControl is Context, IAccessControl, ERC165 { 51 | | struct RoleData { 52 | | mapping(address => bool) members; 53 | | bytes32 adminRole; 54 | | } 55 | | 56 | | mapping(bytes32 => RoleData) private _roles; 57 | | 58 | | bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; 59 | | 60 | | /** 61 | | * @dev Modifier that checks that an account has a specific role. Reverts 62 | | * with a standardized message including the required role. 63 | | * 64 | | * The format of the revert reason is given by the following regular expression: 65 | | * 66 | | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ 67 | | * 68 | | * _Available since v4.1._ 69 | | */ 70 | | modifier onlyRole(bytes32 role) { 71 | | _checkRole(role); 72 | | _; 73 | | } 74 | | 75 | | /** 76 | | * @dev See {IERC165-supportsInterface}. 77 | | */ 78 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 79 | | return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); 80 | | } 81 | | 82 | | /** 83 | | * @dev Returns `true` if `account` has been granted `role`. 84 | | */ 85 | | function hasRole(bytes32 role, address account) public view virtual override returns (bool) { 86 | | return _roles[role].members[account]; 87 | | } 88 | | 89 | | /** 90 | | * @dev Revert with a standard message if `_msgSender()` is missing `role`. 91 | | * Overriding this function changes the behavior of the {onlyRole} modifier. 92 | | * 93 | | * Format of the revert message is described in {_checkRole}. 94 | | * 95 | | * _Available since v4.6._ 96 | | */ 97 | | function _checkRole(bytes32 role) internal view virtual { 98 | | _checkRole(role, _msgSender()); 99 | | } 100 | | 101 | | /** 102 | | * @dev Revert with a standard message if `account` is missing `role`. 103 | | * 104 | | * The format of the revert reason is given by the following regular expression: 105 | | * 106 | | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ 107 | | */ 108 | | function _checkRole(bytes32 role, address account) internal view virtual { 109 | | if (!hasRole(role, account)) { 110 | | revert( 111 | | string( 112 | | abi.encodePacked( 113 | | "AccessControl: account ", 114 | | Strings.toHexString(account), 115 | | " is missing role ", 116 | | Strings.toHexString(uint256(role), 32) 117 | | ) 118 | | ) 119 | | ); 120 | | } 121 | | } 122 | | 123 | | /** 124 | | * @dev Returns the admin role that controls `role`. See {grantRole} and 125 | | * {revokeRole}. 126 | | * 127 | | * To change a role's admin, use {_setRoleAdmin}. 128 | | */ 129 | | function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { 130 | | return _roles[role].adminRole; 131 | | } 132 | | 133 | | /** 134 | | * @dev Grants `role` to `account`. 135 | | * 136 | | * If `account` had not been already granted `role`, emits a {RoleGranted} 137 | | * event. 138 | | * 139 | | * Requirements: 140 | | * 141 | | * - the caller must have ``role``'s admin role. 142 | | * 143 | | * May emit a {RoleGranted} event. 144 | | */ 145 | | function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { 146 | | _grantRole(role, account); 147 | | } 148 | | 149 | | /** 150 | | * @dev Revokes `role` from `account`. 151 | | * 152 | | * If `account` had been granted `role`, emits a {RoleRevoked} event. 153 | | * 154 | | * Requirements: 155 | | * 156 | | * - the caller must have ``role``'s admin role. 157 | | * 158 | | * May emit a {RoleRevoked} event. 159 | | */ 160 | | function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { 161 | | _revokeRole(role, account); 162 | | } 163 | | 164 | | /** 165 | | * @dev Revokes `role` from the calling account. 166 | | * 167 | | * Roles are often managed via {grantRole} and {revokeRole}: this function's 168 | | * purpose is to provide a mechanism for accounts to lose their privileges 169 | | * if they are compromised (such as when a trusted device is misplaced). 170 | | * 171 | | * If the calling account had been revoked `role`, emits a {RoleRevoked} 172 | | * event. 173 | | * 174 | | * Requirements: 175 | | * 176 | | * - the caller must be `account`. 177 | | * 178 | | * May emit a {RoleRevoked} event. 179 | | */ 180 | | function renounceRole(bytes32 role, address account) public virtual override { 181 | | require(account == _msgSender(), "AccessControl: can only renounce roles for self"); 182 | | 183 | | _revokeRole(role, account); 184 | | } 185 | | 186 | | /** 187 | | * @dev Grants `role` to `account`. 188 | | * 189 | | * If `account` had not been already granted `role`, emits a {RoleGranted} 190 | | * event. Note that unlike {grantRole}, this function doesn't perform any 191 | | * checks on the calling account. 192 | | * 193 | | * May emit a {RoleGranted} event. 194 | | * 195 | | * [WARNING] 196 | | * ==== 197 | | * This function should only be called from the constructor when setting 198 | | * up the initial roles for the system. 199 | | * 200 | | * Using this function in any other way is effectively circumventing the admin 201 | | * system imposed by {AccessControl}. 202 | | * ==== 203 | | * 204 | | * NOTE: This function is deprecated in favor of {_grantRole}. 205 | | */ 206 | | function _setupRole(bytes32 role, address account) internal virtual { 207 | | _grantRole(role, account); 208 | | } 209 | | 210 | | /** 211 | | * @dev Sets `adminRole` as ``role``'s admin role. 212 | | * 213 | | * Emits a {RoleAdminChanged} event. 214 | | */ 215 | | function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { 216 | | bytes32 previousAdminRole = getRoleAdmin(role); 217 | | _roles[role].adminRole = adminRole; 218 | | emit RoleAdminChanged(role, previousAdminRole, adminRole); 219 | | } 220 | | 221 | | /** 222 | | * @dev Grants `role` to `account`. 223 | | * 224 | | * Internal function without access restriction. 225 | | * 226 | | * May emit a {RoleGranted} event. 227 | | */ 228 | | function _grantRole(bytes32 role, address account) internal virtual { 229 | | if (!hasRole(role, account)) { 230 | | _roles[role].members[account] = true; 231 | | emit RoleGranted(role, account, _msgSender()); 232 | | } 233 | | } 234 | | 235 | | /** 236 | | * @dev Revokes `role` from `account`. 237 | | * 238 | | * Internal function without access restriction. 239 | | * 240 | | * May emit a {RoleRevoked} event. 241 | | */ 242 | | function _revokeRole(bytes32 role, address account) internal virtual { 243 | | if (hasRole(role, account)) { 244 | | _roles[role].members[account] = false; 245 | | emit RoleRevoked(role, account, _msgSender()); 246 | | } 247 | | } 248 | | } 249 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/IAccessControl.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev External interface of AccessControl declared to support ERC165 detection. 8 | | */ 9 | | interface IAccessControl { 10 | | /** 11 | | * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` 12 | | * 13 | | * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite 14 | | * {RoleAdminChanged} not being emitted signaling this. 15 | | * 16 | | * _Available since v3.1._ 17 | | */ 18 | | event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); 19 | | 20 | | /** 21 | | * @dev Emitted when `account` is granted `role`. 22 | | * 23 | | * `sender` is the account that originated the contract call, an admin role 24 | | * bearer except when using {AccessControl-_setupRole}. 25 | | */ 26 | | event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); 27 | | 28 | | /** 29 | | * @dev Emitted when `account` is revoked `role`. 30 | | * 31 | | * `sender` is the account that originated the contract call: 32 | | * - if using `revokeRole`, it is the admin role bearer 33 | | * - if using `renounceRole`, it is the role bearer (i.e. `account`) 34 | | */ 35 | | event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); 36 | | 37 | | /** 38 | | * @dev Returns `true` if `account` has been granted `role`. 39 | | */ 40 | | function hasRole(bytes32 role, address account) external view returns (bool); 41 | | 42 | | /** 43 | | * @dev Returns the admin role that controls `role`. See {grantRole} and 44 | | * {revokeRole}. 45 | | * 46 | | * To change a role's admin, use {AccessControl-_setRoleAdmin}. 47 | | */ 48 | | function getRoleAdmin(bytes32 role) external view returns (bytes32); 49 | | 50 | | /** 51 | | * @dev Grants `role` to `account`. 52 | | * 53 | | * If `account` had not been already granted `role`, emits a {RoleGranted} 54 | | * event. 55 | | * 56 | | * Requirements: 57 | | * 58 | | * - the caller must have ``role``'s admin role. 59 | | */ 60 | | function grantRole(bytes32 role, address account) external; 61 | | 62 | | /** 63 | | * @dev Revokes `role` from `account`. 64 | | * 65 | | * If `account` had been granted `role`, emits a {RoleRevoked} event. 66 | | * 67 | | * Requirements: 68 | | * 69 | | * - the caller must have ``role``'s admin role. 70 | | */ 71 | | function revokeRole(bytes32 role, address account) external; 72 | | 73 | | /** 74 | | * @dev Revokes `role` from the calling account. 75 | | * 76 | | * Roles are often managed via {grantRole} and {revokeRole}: this function's 77 | | * purpose is to provide a mechanism for accounts to lose their privileges 78 | | * if they are compromised (such as when a trusted device is misplaced). 79 | | * 80 | | * If the calling account had been granted `role`, emits a {RoleRevoked} 81 | | * event. 82 | | * 83 | | * Requirements: 84 | | * 85 | | * - the caller must be `account`. 86 | | */ 87 | | function renounceRole(bytes32 role, address account) external; 88 | | } 89 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/access/Ownable.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../utils/Context.sol"; 7 | | 8 | | /** 9 | | * @dev Contract module which provides a basic access control mechanism, where 10 | | * there is an account (an owner) that can be granted exclusive access to 11 | | * specific functions. 12 | | * 13 | | * By default, the owner account will be the one that deploys the contract. This 14 | | * can later be changed with {transferOwnership}. 15 | | * 16 | | * This module is used through inheritance. It will make available the modifier 17 | | * `onlyOwner`, which can be applied to your functions to restrict their use to 18 | | * the owner. 19 | | */ 20 | | abstract contract Ownable is Context { 21 | | address private _owner; 22 | | 23 | | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 24 | | 25 | | /** 26 | | * @dev Initializes the contract setting the deployer as the initial owner. 27 | | */ 28 | | constructor() { 29 | | _transferOwnership(_msgSender()); 30 | | } 31 | | 32 | | /** 33 | | * @dev Throws if called by any account other than the owner. 34 | | */ 35 | | modifier onlyOwner() { 36 | | _checkOwner(); 37 | | _; 38 | | } 39 | | 40 | | /** 41 | | * @dev Returns the address of the current owner. 42 | | */ 43 | | function owner() public view virtual returns (address) { 44 | | return _owner; 45 | | } 46 | | 47 | | /** 48 | | * @dev Throws if the sender is not the owner. 49 | | */ 50 | | function _checkOwner() internal view virtual { 51 | | require(owner() == _msgSender(), "Ownable: caller is not the owner"); 52 | | } 53 | | 54 | | /** 55 | | * @dev Leaves the contract without owner. It will not be possible to call 56 | | * `onlyOwner` functions. Can only be called by the current owner. 57 | | * 58 | | * NOTE: Renouncing ownership will leave the contract without an owner, 59 | | * thereby disabling any functionality that is only available to the owner. 60 | | */ 61 | | function renounceOwnership() public virtual onlyOwner { 62 | | _transferOwnership(address(0)); 63 | | } 64 | | 65 | | /** 66 | | * @dev Transfers ownership of the contract to a new account (`newOwner`). 67 | | * Can only be called by the current owner. 68 | | */ 69 | | function transferOwnership(address newOwner) public virtual onlyOwner { 70 | | require(newOwner != address(0), "Ownable: new owner is the zero address"); 71 | | _transferOwnership(newOwner); 72 | | } 73 | | 74 | | /** 75 | | * @dev Transfers ownership of the contract to a new account (`newOwner`). 76 | | * Internal function without access restriction. 77 | | */ 78 | | function _transferOwnership(address newOwner) internal virtual { 79 | | address oldOwner = _owner; 80 | | _owner = newOwner; 81 | | emit OwnershipTransferred(oldOwner, newOwner); 82 | | } 83 | | } 84 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/Governor.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.1) (governance/Governor.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../token/ERC721/IERC721Receiver.sol"; 7 | | import "../token/ERC1155/IERC1155Receiver.sol"; 8 | | import "../utils/cryptography/ECDSA.sol"; 9 | | import "../utils/cryptography/EIP712.sol"; 10 | | import "../utils/introspection/ERC165.sol"; 11 | | import "../utils/math/SafeCast.sol"; 12 | | import "../utils/structs/DoubleEndedQueue.sol"; 13 | | import "../utils/Address.sol"; 14 | | import "../utils/Context.sol"; 15 | | import "./IGovernor.sol"; 16 | | 17 | | /** 18 | | * @dev Core of the governance system, designed to be extended though various modules. 19 | | * 20 | | * This contract is abstract and requires several functions to be implemented in various modules: 21 | | * 22 | | * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote} 23 | | * - A voting module must implement {_getVotes} 24 | | * - Additionally, {votingPeriod} must also be implemented 25 | | * 26 | | * _Available since v4.3._ 27 | | */ 28 | | abstract contract Governor is Context, ERC165, EIP712, IGovernor, IERC721Receiver, IERC1155Receiver { 29 | | using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque; 30 | | 31 | | bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)"); 32 | | bytes32 public constant EXTENDED_BALLOT_TYPEHASH = 33 | | keccak256("ExtendedBallot(uint256 proposalId,uint8 support,string reason,bytes params)"); 34 | | 35 | | // solhint-disable var-name-mixedcase 36 | | struct ProposalCore { 37 | | // --- start retyped from Timers.BlockNumber at offset 0x00 --- 38 | | uint64 voteStart; 39 | | address proposer; 40 | | bytes4 __gap_unused0; 41 | | // --- start retyped from Timers.BlockNumber at offset 0x20 --- 42 | | uint64 voteEnd; 43 | | bytes24 __gap_unused1; 44 | | // --- Remaining fields starting at offset 0x40 --------------- 45 | | bool executed; 46 | | bool canceled; 47 | | } 48 | | // solhint-enable var-name-mixedcase 49 | | 50 | | string private _name; 51 | | 52 | | /// @custom:oz-retyped-from mapping(uint256 => Governor.ProposalCore) 53 | | mapping(uint256 => ProposalCore) private _proposals; 54 | | 55 | | // This queue keeps track of the governor operating on itself. Calls to functions protected by the 56 | | // {onlyGovernance} modifier needs to be whitelisted in this queue. Whitelisting is set in {_beforeExecute}, 57 | | // consumed by the {onlyGovernance} modifier and eventually reset in {_afterExecute}. This ensures that the 58 | | // execution of {onlyGovernance} protected calls can only be achieved through successful proposals. 59 | | DoubleEndedQueue.Bytes32Deque private _governanceCall; 60 | | 61 | | /** 62 | | * @dev Restricts a function so it can only be executed through governance proposals. For example, governance 63 | | * parameter setters in {GovernorSettings} are protected using this modifier. 64 | | * 65 | | * The governance executing address may be different from the Governor's own address, for example it could be a 66 | | * timelock. This can be customized by modules by overriding {_executor}. The executor is only able to invoke these 67 | | * functions during the execution of the governor's {execute} function, and not under any other circumstances. Thus, 68 | | * for example, additional timelock proposers are not able to change governance parameters without going through the 69 | | * governance protocol (since v4.6). 70 | | */ 71 | | modifier onlyGovernance() { 72 | | require(_msgSender() == _executor(), "Governor: onlyGovernance"); 73 | | if (_executor() != address(this)) { 74 | | bytes32 msgDataHash = keccak256(_msgData()); 75 | | // loop until popping the expected operation - throw if deque is empty (operation not authorized) 76 | | while (_governanceCall.popFront() != msgDataHash) {} 77 | | } 78 | | _; 79 | | } 80 | | 81 | | /** 82 | | * @dev Sets the value for {name} and {version} 83 | | */ 84 | | constructor(string memory name_) EIP712(name_, version()) { 85 | | _name = name_; 86 | | } 87 | | 88 | | /** 89 | | * @dev Function to receive ETH that will be handled by the governor (disabled if executor is a third party contract) 90 | | */ 91 | | receive() external payable virtual { 92 | | require(_executor() == address(this), "Governor: must send to executor"); 93 | | } 94 | | 95 | | /** 96 | | * @dev See {IERC165-supportsInterface}. 97 | | */ 98 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { 99 | | bytes4 governorCancelId = this.cancel.selector ^ this.proposalProposer.selector; 100 | | 101 | | bytes4 governorParamsId = this.castVoteWithReasonAndParams.selector ^ 102 | | this.castVoteWithReasonAndParamsBySig.selector ^ 103 | | this.getVotesWithParams.selector; 104 | | 105 | | // The original interface id in v4.3. 106 | | bytes4 governor43Id = type(IGovernor).interfaceId ^ 107 | | type(IERC6372).interfaceId ^ 108 | | governorCancelId ^ 109 | | governorParamsId; 110 | | 111 | | // An updated interface id in v4.6, with params added. 112 | | bytes4 governor46Id = type(IGovernor).interfaceId ^ type(IERC6372).interfaceId ^ governorCancelId; 113 | | 114 | | // For the updated interface id in v4.9, we use governorCancelId directly. 115 | | 116 | | return 117 | | interfaceId == governor43Id || 118 | | interfaceId == governor46Id || 119 | | interfaceId == governorCancelId || 120 | | interfaceId == type(IERC1155Receiver).interfaceId || 121 | | super.supportsInterface(interfaceId); 122 | | } 123 | | 124 | | /** 125 | | * @dev See {IGovernor-name}. 126 | | */ 127 | | function name() public view virtual override returns (string memory) { 128 | | return _name; 129 | | } 130 | | 131 | | /** 132 | | * @dev See {IGovernor-version}. 133 | | */ 134 | | function version() public view virtual override returns (string memory) { 135 | | return "1"; 136 | | } 137 | | 138 | | /** 139 | | * @dev See {IGovernor-hashProposal}. 140 | | * 141 | | * The proposal id is produced by hashing the ABI encoded `targets` array, the `values` array, the `calldatas` array 142 | | * and the descriptionHash (bytes32 which itself is the keccak256 hash of the description string). This proposal id 143 | | * can be produced from the proposal data which is part of the {ProposalCreated} event. It can even be computed in 144 | | * advance, before the proposal is submitted. 145 | | * 146 | | * Note that the chainId and the governor address are not part of the proposal id computation. Consequently, the 147 | | * same proposal (with same operation and same description) will have the same id if submitted on multiple governors 148 | | * across multiple networks. This also means that in order to execute the same operation twice (on the same 149 | | * governor) the proposer will have to change the description in order to avoid proposal id conflicts. 150 | | */ 151 | | function hashProposal( 152 | | address[] memory targets, 153 | | uint256[] memory values, 154 | | bytes[] memory calldatas, 155 | | bytes32 descriptionHash 156 | | ) public pure virtual override returns (uint256) { 157 | | return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash))); 158 | | } 159 | | 160 | | /** 161 | | * @dev See {IGovernor-state}. 162 | | */ 163 | | function state(uint256 proposalId) public view virtual override returns (ProposalState) { 164 | | ProposalCore storage proposal = _proposals[proposalId]; 165 | | 166 | | if (proposal.executed) { 167 | | return ProposalState.Executed; 168 | | } 169 | | 170 | | if (proposal.canceled) { 171 | | return ProposalState.Canceled; 172 | | } 173 | | 174 | | uint256 snapshot = proposalSnapshot(proposalId); 175 | | 176 | | if (snapshot == 0) { 177 | | revert("Governor: unknown proposal id"); 178 | | } 179 | | 180 | | uint256 currentTimepoint = clock(); 181 | | 182 | | if (snapshot >= currentTimepoint) { 183 | | return ProposalState.Pending; 184 | | } 185 | | 186 | | uint256 deadline = proposalDeadline(proposalId); 187 | | 188 | | if (deadline >= currentTimepoint) { 189 | | return ProposalState.Active; 190 | | } 191 | | 192 | | if (_quorumReached(proposalId) && _voteSucceeded(proposalId)) { 193 | | return ProposalState.Succeeded; 194 | | } else { 195 | | return ProposalState.Defeated; 196 | | } 197 | | } 198 | | 199 | | /** 200 | | * @dev Part of the Governor Bravo's interface: _"The number of votes required in order for a voter to become a proposer"_. 201 | | */ 202 | | function proposalThreshold() public view virtual returns (uint256) { 203 | | return 0; 204 | | } 205 | | 206 | | /** 207 | | * @dev See {IGovernor-proposalSnapshot}. 208 | | */ 209 | | function proposalSnapshot(uint256 proposalId) public view virtual override returns (uint256) { 210 | | return _proposals[proposalId].voteStart; 211 | | } 212 | | 213 | | /** 214 | | * @dev See {IGovernor-proposalDeadline}. 215 | | */ 216 | | function proposalDeadline(uint256 proposalId) public view virtual override returns (uint256) { 217 | | return _proposals[proposalId].voteEnd; 218 | | } 219 | | 220 | | /** 221 | | * @dev Returns the account that created a given proposal. 222 | | */ 223 | | function proposalProposer(uint256 proposalId) public view virtual override returns (address) { 224 | | return _proposals[proposalId].proposer; 225 | | } 226 | | 227 | | /** 228 | | * @dev Amount of votes already cast passes the threshold limit. 229 | | */ 230 | | function _quorumReached(uint256 proposalId) internal view virtual returns (bool); 231 | | 232 | | /** 233 | | * @dev Is the proposal successful or not. 234 | | */ 235 | | function _voteSucceeded(uint256 proposalId) internal view virtual returns (bool); 236 | | 237 | | /** 238 | | * @dev Get the voting weight of `account` at a specific `timepoint`, for a vote as described by `params`. 239 | | */ 240 | | function _getVotes(address account, uint256 timepoint, bytes memory params) internal view virtual returns (uint256); 241 | | 242 | | /** 243 | | * @dev Register a vote for `proposalId` by `account` with a given `support`, voting `weight` and voting `params`. 244 | | * 245 | | * Note: Support is generic and can represent various things depending on the voting system used. 246 | | */ 247 | | function _countVote( 248 | | uint256 proposalId, 249 | | address account, 250 | | uint8 support, 251 | | uint256 weight, 252 | | bytes memory params 253 | | ) internal virtual; 254 | | 255 | | /** 256 | | * @dev Default additional encoded parameters used by castVote methods that don't include them 257 | | * 258 | | * Note: Should be overridden by specific implementations to use an appropriate value, the 259 | | * meaning of the additional params, in the context of that implementation 260 | | */ 261 | | function _defaultParams() internal view virtual returns (bytes memory) { 262 | | return ""; 263 | | } 264 | | 265 | | /** 266 | | * @dev See {IGovernor-propose}. This function has opt-in frontrunning protection, described in {_isValidDescriptionForProposer}. 267 | | */ 268 | | function propose( 269 | | address[] memory targets, 270 | | uint256[] memory values, 271 | | bytes[] memory calldatas, 272 | | string memory description 273 | | ) public virtual override returns (uint256) { 274 | | address proposer = _msgSender(); 275 | | require(_isValidDescriptionForProposer(proposer, description), "Governor: proposer restricted"); 276 | | 277 | | uint256 currentTimepoint = clock(); 278 | | require( 279 | | getVotes(proposer, currentTimepoint - 1) >= proposalThreshold(), 280 | | "Governor: proposer votes below proposal threshold" 281 | | ); 282 | | 283 | | uint256 proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description))); 284 | | 285 | | require(targets.length == values.length, "Governor: invalid proposal length"); 286 | | require(targets.length == calldatas.length, "Governor: invalid proposal length"); 287 | | require(targets.length > 0, "Governor: empty proposal"); 288 | | require(_proposals[proposalId].voteStart == 0, "Governor: proposal already exists"); 289 | | 290 | | uint256 snapshot = currentTimepoint + votingDelay(); 291 | | uint256 deadline = snapshot + votingPeriod(); 292 | | 293 | | _proposals[proposalId] = ProposalCore({ 294 | | proposer: proposer, 295 | | voteStart: SafeCast.toUint64(snapshot), 296 | | voteEnd: SafeCast.toUint64(deadline), 297 | | executed: false, 298 | | canceled: false, 299 | | __gap_unused0: 0, 300 | | __gap_unused1: 0 301 | | }); 302 | | 303 | | emit ProposalCreated( 304 | | proposalId, 305 | | proposer, 306 | | targets, 307 | | values, 308 | | new string[](targets.length), 309 | | calldatas, 310 | | snapshot, 311 | | deadline, 312 | | description 313 | | ); 314 | | 315 | | return proposalId; 316 | | } 317 | | 318 | | /** 319 | | * @dev See {IGovernor-execute}. 320 | | */ 321 | | function execute( 322 | | address[] memory targets, 323 | | uint256[] memory values, 324 | | bytes[] memory calldatas, 325 | | bytes32 descriptionHash 326 | | ) public payable virtual override returns (uint256) { 327 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); 328 | | 329 | | ProposalState currentState = state(proposalId); 330 | | require( 331 | | currentState == ProposalState.Succeeded || currentState == ProposalState.Queued, 332 | | "Governor: proposal not successful" 333 | | ); 334 | | _proposals[proposalId].executed = true; 335 | | 336 | | emit ProposalExecuted(proposalId); 337 | | 338 | | _beforeExecute(proposalId, targets, values, calldatas, descriptionHash); 339 | | _execute(proposalId, targets, values, calldatas, descriptionHash); 340 | | _afterExecute(proposalId, targets, values, calldatas, descriptionHash); 341 | | 342 | | return proposalId; 343 | | } 344 | | 345 | | /** 346 | | * @dev See {IGovernor-cancel}. 347 | | */ 348 | | function cancel( 349 | | address[] memory targets, 350 | | uint256[] memory values, 351 | | bytes[] memory calldatas, 352 | | bytes32 descriptionHash 353 | | ) public virtual override returns (uint256) { 354 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); 355 | | require(state(proposalId) == ProposalState.Pending, "Governor: too late to cancel"); 356 | | require(_msgSender() == _proposals[proposalId].proposer, "Governor: only proposer can cancel"); 357 | | return _cancel(targets, values, calldatas, descriptionHash); 358 | | } 359 | | 360 | | /** 361 | | * @dev Internal execution mechanism. Can be overridden to implement different execution mechanism 362 | | */ 363 | | function _execute( 364 | | uint256 /* proposalId */, 365 | | address[] memory targets, 366 | | uint256[] memory values, 367 | | bytes[] memory calldatas, 368 | | bytes32 /*descriptionHash*/ 369 | | ) internal virtual { 370 | | string memory errorMessage = "Governor: call reverted without message"; 371 | | for (uint256 i = 0; i < targets.length; ++i) { 372 | | (bool success, bytes memory returndata) = targets[i].call{value: values[i]}(calldatas[i]); 373 | | Address.verifyCallResult(success, returndata, errorMessage); 374 | | } 375 | | } 376 | | 377 | | /** 378 | | * @dev Hook before execution is triggered. 379 | | */ 380 | | function _beforeExecute( 381 | | uint256 /* proposalId */, 382 | | address[] memory targets, 383 | | uint256[] memory /* values */, 384 | | bytes[] memory calldatas, 385 | | bytes32 /*descriptionHash*/ 386 | | ) internal virtual { 387 | | if (_executor() != address(this)) { 388 | | for (uint256 i = 0; i < targets.length; ++i) { 389 | | if (targets[i] == address(this)) { 390 | | _governanceCall.pushBack(keccak256(calldatas[i])); 391 | | } 392 | | } 393 | | } 394 | | } 395 | | 396 | | /** 397 | | * @dev Hook after execution is triggered. 398 | | */ 399 | | function _afterExecute( 400 | | uint256 /* proposalId */, 401 | | address[] memory /* targets */, 402 | | uint256[] memory /* values */, 403 | | bytes[] memory /* calldatas */, 404 | | bytes32 /*descriptionHash*/ 405 | | ) internal virtual { 406 | | if (_executor() != address(this)) { 407 | | if (!_governanceCall.empty()) { 408 | | _governanceCall.clear(); 409 | | } 410 | | } 411 | | } 412 | | 413 | | /** 414 | | * @dev Internal cancel mechanism: locks up the proposal timer, preventing it from being re-submitted. Marks it as 415 | | * canceled to allow distinguishing it from executed proposals. 416 | | * 417 | | * Emits a {IGovernor-ProposalCanceled} event. 418 | | */ 419 | | function _cancel( 420 | | address[] memory targets, 421 | | uint256[] memory values, 422 | | bytes[] memory calldatas, 423 | | bytes32 descriptionHash 424 | | ) internal virtual returns (uint256) { 425 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); 426 | | 427 | | ProposalState currentState = state(proposalId); 428 | | 429 | | require( 430 | | currentState != ProposalState.Canceled && 431 | | currentState != ProposalState.Expired && 432 | | currentState != ProposalState.Executed, 433 | | "Governor: proposal not active" 434 | | ); 435 | | _proposals[proposalId].canceled = true; 436 | | 437 | | emit ProposalCanceled(proposalId); 438 | | 439 | | return proposalId; 440 | | } 441 | | 442 | | /** 443 | | * @dev See {IGovernor-getVotes}. 444 | | */ 445 | | function getVotes(address account, uint256 timepoint) public view virtual override returns (uint256) { 446 | | return _getVotes(account, timepoint, _defaultParams()); 447 | | } 448 | | 449 | | /** 450 | | * @dev See {IGovernor-getVotesWithParams}. 451 | | */ 452 | | function getVotesWithParams( 453 | | address account, 454 | | uint256 timepoint, 455 | | bytes memory params 456 | | ) public view virtual override returns (uint256) { 457 | | return _getVotes(account, timepoint, params); 458 | | } 459 | | 460 | | /** 461 | | * @dev See {IGovernor-castVote}. 462 | | */ 463 | | function castVote(uint256 proposalId, uint8 support) public virtual override returns (uint256) { 464 | | address voter = _msgSender(); 465 | | return _castVote(proposalId, voter, support, ""); 466 | | } 467 | | 468 | | /** 469 | | * @dev See {IGovernor-castVoteWithReason}. 470 | | */ 471 | | function castVoteWithReason( 472 | | uint256 proposalId, 473 | | uint8 support, 474 | | string calldata reason 475 | | ) public virtual override returns (uint256) { 476 | | address voter = _msgSender(); 477 | | return _castVote(proposalId, voter, support, reason); 478 | | } 479 | | 480 | | /** 481 | | * @dev See {IGovernor-castVoteWithReasonAndParams}. 482 | | */ 483 | | function castVoteWithReasonAndParams( 484 | | uint256 proposalId, 485 | | uint8 support, 486 | | string calldata reason, 487 | | bytes memory params 488 | | ) public virtual override returns (uint256) { 489 | | address voter = _msgSender(); 490 | | return _castVote(proposalId, voter, support, reason, params); 491 | | } 492 | | 493 | | /** 494 | | * @dev See {IGovernor-castVoteBySig}. 495 | | */ 496 | | function castVoteBySig( 497 | | uint256 proposalId, 498 | | uint8 support, 499 | | uint8 v, 500 | | bytes32 r, 501 | | bytes32 s 502 | | ) public virtual override returns (uint256) { 503 | | address voter = ECDSA.recover( 504 | | _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support))), 505 | | v, 506 | | r, 507 | | s 508 | | ); 509 | | return _castVote(proposalId, voter, support, ""); 510 | | } 511 | | 512 | | /** 513 | | * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}. 514 | | */ 515 | | function castVoteWithReasonAndParamsBySig( 516 | | uint256 proposalId, 517 | | uint8 support, 518 | | string calldata reason, 519 | | bytes memory params, 520 | | uint8 v, 521 | | bytes32 r, 522 | | bytes32 s 523 | | ) public virtual override returns (uint256) { 524 | | address voter = ECDSA.recover( 525 | | _hashTypedDataV4( 526 | | keccak256( 527 | | abi.encode( 528 | | EXTENDED_BALLOT_TYPEHASH, 529 | | proposalId, 530 | | support, 531 | | keccak256(bytes(reason)), 532 | | keccak256(params) 533 | | ) 534 | | ) 535 | | ), 536 | | v, 537 | | r, 538 | | s 539 | | ); 540 | | 541 | | return _castVote(proposalId, voter, support, reason, params); 542 | | } 543 | | 544 | | /** 545 | | * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve 546 | | * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams(). 547 | | * 548 | | * Emits a {IGovernor-VoteCast} event. 549 | | */ 550 | | function _castVote( 551 | | uint256 proposalId, 552 | | address account, 553 | | uint8 support, 554 | | string memory reason 555 | | ) internal virtual returns (uint256) { 556 | | return _castVote(proposalId, account, support, reason, _defaultParams()); 557 | | } 558 | | 559 | | /** 560 | | * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve 561 | | * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. 562 | | * 563 | | * Emits a {IGovernor-VoteCast} event. 564 | | */ 565 | | function _castVote( 566 | | uint256 proposalId, 567 | | address account, 568 | | uint8 support, 569 | | string memory reason, 570 | | bytes memory params 571 | | ) internal virtual returns (uint256) { 572 | | ProposalCore storage proposal = _proposals[proposalId]; 573 | | require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active"); 574 | | 575 | | uint256 weight = _getVotes(account, proposal.voteStart, params); 576 | | _countVote(proposalId, account, support, weight, params); 577 | | 578 | | if (params.length == 0) { 579 | | emit VoteCast(account, proposalId, support, weight, reason); 580 | | } else { 581 | | emit VoteCastWithParams(account, proposalId, support, weight, reason, params); 582 | | } 583 | | 584 | | return weight; 585 | | } 586 | | 587 | | /** 588 | | * @dev Relays a transaction or function call to an arbitrary target. In cases where the governance executor 589 | | * is some contract other than the governor itself, like when using a timelock, this function can be invoked 590 | | * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. 591 | | * Note that if the executor is simply the governor itself, use of `relay` is redundant. 592 | | */ 593 | | function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance { 594 | | (bool success, bytes memory returndata) = target.call{value: value}(data); 595 | | Address.verifyCallResult(success, returndata, "Governor: relay reverted without message"); 596 | | } 597 | | 598 | | /** 599 | | * @dev Address through which the governor executes action. Will be overloaded by module that execute actions 600 | | * through another contract such as a timelock. 601 | | */ 602 | | function _executor() internal view virtual returns (address) { 603 | | return address(this); 604 | | } 605 | | 606 | | /** 607 | | * @dev See {IERC721Receiver-onERC721Received}. 608 | | */ 609 | | function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) { 610 | | return this.onERC721Received.selector; 611 | | } 612 | | 613 | | /** 614 | | * @dev See {IERC1155Receiver-onERC1155Received}. 615 | | */ 616 | | function onERC1155Received( 617 | | address, 618 | | address, 619 | | uint256, 620 | | uint256, 621 | | bytes memory 622 | | ) public virtual override returns (bytes4) { 623 | | return this.onERC1155Received.selector; 624 | | } 625 | | 626 | | /** 627 | | * @dev See {IERC1155Receiver-onERC1155BatchReceived}. 628 | | */ 629 | | function onERC1155BatchReceived( 630 | | address, 631 | | address, 632 | | uint256[] memory, 633 | | uint256[] memory, 634 | | bytes memory 635 | | ) public virtual override returns (bytes4) { 636 | | return this.onERC1155BatchReceived.selector; 637 | | } 638 | | 639 | | /** 640 | | * @dev Check if the proposer is authorized to submit a proposal with the given description. 641 | | * 642 | | * If the proposal description ends with `#proposer=0x???`, where `0x???` is an address written as a hex string 643 | | * (case insensitive), then the submission of this proposal will only be authorized to said address. 644 | | * 645 | | * This is used for frontrunning protection. By adding this pattern at the end of their proposal, one can ensure 646 | | * that no other address can submit the same proposal. An attacker would have to either remove or change that part, 647 | | * which would result in a different proposal id. 648 | | * 649 | | * If the description does not match this pattern, it is unrestricted and anyone can submit it. This includes: 650 | | * - If the `0x???` part is not a valid hex string. 651 | | * - If the `0x???` part is a valid hex string, but does not contain exactly 40 hex digits. 652 | | * - If it ends with the expected suffix followed by newlines or other whitespace. 653 | | * - If it ends with some other similar suffix, e.g. `#other=abc`. 654 | | * - If it does not end with any such suffix. 655 | | */ 656 | | function _isValidDescriptionForProposer( 657 | | address proposer, 658 | | string memory description 659 | | ) internal view virtual returns (bool) { 660 | | uint256 len = bytes(description).length; 661 | | 662 | | // Length is too short to contain a valid proposer suffix 663 | | if (len < 52) { 664 | | return true; 665 | | } 666 | | 667 | | // Extract what would be the `#proposer=0x` marker beginning the suffix 668 | | bytes12 marker; 669 | | assembly { 670 | | // - Start of the string contents in memory = description + 32 671 | | // - First character of the marker = len - 52 672 | | // - Length of "#proposer=0x0000000000000000000000000000000000000000" = 52 673 | | // - We read the memory word starting at the first character of the marker: 674 | | // - (description + 32) + (len - 52) = description + (len - 20) 675 | | // - Note: Solidity will ignore anything past the first 12 bytes 676 | | marker := mload(add(description, sub(len, 20))) 677 | | } 678 | | 679 | | // If the marker is not found, there is no proposer suffix to check 680 | | if (marker != bytes12("#proposer=0x")) { 681 | | return true; 682 | | } 683 | | 684 | | // Parse the 40 characters following the marker as uint160 685 | | uint160 recovered = 0; 686 | | for (uint256 i = len - 40; i < len; ++i) { 687 | | (bool isHex, uint8 value) = _tryHexToUint(bytes(description)[i]); 688 | | // If any of the characters is not a hex digit, ignore the suffix entirely 689 | | if (!isHex) { 690 | | return true; 691 | | } 692 | | recovered = (recovered << 4) | value; 693 | | } 694 | | 695 | | return recovered == uint160(proposer); 696 | | } 697 | | 698 | | /** 699 | | * @dev Try to parse a character from a string as a hex value. Returns `(true, value)` if the char is in 700 | | * `[0-9a-fA-F]` and `(false, 0)` otherwise. Value is guaranteed to be in the range `0 <= value < 16` 701 | | */ 702 | | function _tryHexToUint(bytes1 char) private pure returns (bool, uint8) { 703 | | uint8 c = uint8(char); 704 | | unchecked { 705 | | // Case 0-9 706 | | if (47 < c && c < 58) { 707 | | return (true, c - 48); 708 | | } 709 | | // Case A-F 710 | | else if (64 < c && c < 71) { 711 | | return (true, c - 55); 712 | | } 713 | | // Case a-f 714 | | else if (96 < c && c < 103) { 715 | | return (true, c - 87); 716 | | } 717 | | // Else: not a hex char 718 | | else { 719 | | return (false, 0); 720 | | } 721 | | } 722 | | } 723 | | } 724 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/IGovernor.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/IGovernor.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../interfaces/IERC165.sol"; 7 | | import "../interfaces/IERC6372.sol"; 8 | | 9 | | /** 10 | | * @dev Interface of the {Governor} core. 11 | | * 12 | | * _Available since v4.3._ 13 | | */ 14 | | abstract contract IGovernor is IERC165, IERC6372 { 15 | | enum ProposalState { 16 | | Pending, 17 | | Active, 18 | | Canceled, 19 | | Defeated, 20 | | Succeeded, 21 | | Queued, 22 | | Expired, 23 | | Executed 24 | | } 25 | | 26 | | /** 27 | | * @dev Emitted when a proposal is created. 28 | | */ 29 | | event ProposalCreated( 30 | | uint256 proposalId, 31 | | address proposer, 32 | | address[] targets, 33 | | uint256[] values, 34 | | string[] signatures, 35 | | bytes[] calldatas, 36 | | uint256 voteStart, 37 | | uint256 voteEnd, 38 | | string description 39 | | ); 40 | | 41 | | /** 42 | | * @dev Emitted when a proposal is canceled. 43 | | */ 44 | | event ProposalCanceled(uint256 proposalId); 45 | | 46 | | /** 47 | | * @dev Emitted when a proposal is executed. 48 | | */ 49 | | event ProposalExecuted(uint256 proposalId); 50 | | 51 | | /** 52 | | * @dev Emitted when a vote is cast without params. 53 | | * 54 | | * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used. 55 | | */ 56 | | event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason); 57 | | 58 | | /** 59 | | * @dev Emitted when a vote is cast with params. 60 | | * 61 | | * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used. 62 | | * `params` are additional encoded parameters. Their interpepretation also depends on the voting module used. 63 | | */ 64 | | event VoteCastWithParams( 65 | | address indexed voter, 66 | | uint256 proposalId, 67 | | uint8 support, 68 | | uint256 weight, 69 | | string reason, 70 | | bytes params 71 | | ); 72 | | 73 | | /** 74 | | * @notice module:core 75 | | * @dev Name of the governor instance (used in building the ERC712 domain separator). 76 | | */ 77 | | function name() public view virtual returns (string memory); 78 | | 79 | | /** 80 | | * @notice module:core 81 | | * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1" 82 | | */ 83 | | function version() public view virtual returns (string memory); 84 | | 85 | | /** 86 | | * @notice module:core 87 | | * @dev See {IERC6372} 88 | | */ 89 | | function clock() public view virtual override returns (uint48); 90 | | 91 | | /** 92 | | * @notice module:core 93 | | * @dev See EIP-6372. 94 | | */ 95 | | // solhint-disable-next-line func-name-mixedcase 96 | | function CLOCK_MODE() public view virtual override returns (string memory); 97 | | 98 | | /** 99 | | * @notice module:voting 100 | | * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to 101 | | * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of 102 | | * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`. 103 | | * 104 | | * There are 2 standard keys: `support` and `quorum`. 105 | | * 106 | | * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`. 107 | | * - `quorum=bravo` means that only For votes are counted towards quorum. 108 | | * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum. 109 | | * 110 | | * If a counting module makes use of encoded `params`, it should include this under a `params` key with a unique 111 | | * name that describes the behavior. For example: 112 | | * 113 | | * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain. 114 | | * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote. 115 | | * 116 | | * NOTE: The string can be decoded by the standard 117 | | * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`] 118 | | * JavaScript class. 119 | | */ 120 | | // solhint-disable-next-line func-name-mixedcase 121 | | function COUNTING_MODE() public view virtual returns (string memory); 122 | | 123 | | /** 124 | | * @notice module:core 125 | | * @dev Hashing function used to (re)build the proposal id from the proposal details.. 126 | | */ 127 | | function hashProposal( 128 | | address[] memory targets, 129 | | uint256[] memory values, 130 | | bytes[] memory calldatas, 131 | | bytes32 descriptionHash 132 | | ) public pure virtual returns (uint256); 133 | | 134 | | /** 135 | | * @notice module:core 136 | | * @dev Current state of a proposal, following Compound's convention 137 | | */ 138 | | function state(uint256 proposalId) public view virtual returns (ProposalState); 139 | | 140 | | /** 141 | | * @notice module:core 142 | | * @dev Timepoint used to retrieve user's votes and quorum. If using block number (as per Compound's Comp), the 143 | | * snapshot is performed at the end of this block. Hence, voting for this proposal starts at the beginning of the 144 | | * following block. 145 | | */ 146 | | function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256); 147 | | 148 | | /** 149 | | * @notice module:core 150 | | * @dev Timepoint at which votes close. If using block number, votes close at the end of this block, so it is 151 | | * possible to cast a vote during this block. 152 | | */ 153 | | function proposalDeadline(uint256 proposalId) public view virtual returns (uint256); 154 | | 155 | | /** 156 | | * @notice module:core 157 | | * @dev The account that created a proposal. 158 | | */ 159 | | function proposalProposer(uint256 proposalId) public view virtual returns (address); 160 | | 161 | | /** 162 | | * @notice module:user-config 163 | | * @dev Delay, between the proposal is created and the vote starts. The unit this duration is expressed in depends 164 | | * on the clock (see EIP-6372) this contract uses. 165 | | * 166 | | * This can be increased to leave time for users to buy voting power, or delegate it, before the voting of a 167 | | * proposal starts. 168 | | */ 169 | | function votingDelay() public view virtual returns (uint256); 170 | | 171 | | /** 172 | | * @notice module:user-config 173 | | * @dev Delay between the vote start and vote end. The unit this duration is expressed in depends on the clock 174 | | * (see EIP-6372) this contract uses. 175 | | * 176 | | * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting 177 | | * duration compared to the voting delay. 178 | | */ 179 | | function votingPeriod() public view virtual returns (uint256); 180 | | 181 | | /** 182 | | * @notice module:user-config 183 | | * @dev Minimum number of cast voted required for a proposal to be successful. 184 | | * 185 | | * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting vote. This allows to scale the 186 | | * quorum depending on values such as the totalSupply of a token at this timepoint (see {ERC20Votes}). 187 | | */ 188 | | function quorum(uint256 timepoint) public view virtual returns (uint256); 189 | | 190 | | /** 191 | | * @notice module:reputation 192 | | * @dev Voting power of an `account` at a specific `timepoint`. 193 | | * 194 | | * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or 195 | | * multiple), {ERC20Votes} tokens. 196 | | */ 197 | | function getVotes(address account, uint256 timepoint) public view virtual returns (uint256); 198 | | 199 | | /** 200 | | * @notice module:reputation 201 | | * @dev Voting power of an `account` at a specific `timepoint` given additional encoded parameters. 202 | | */ 203 | | function getVotesWithParams( 204 | | address account, 205 | | uint256 timepoint, 206 | | bytes memory params 207 | | ) public view virtual returns (uint256); 208 | | 209 | | /** 210 | | * @notice module:voting 211 | | * @dev Returns whether `account` has cast a vote on `proposalId`. 212 | | */ 213 | | function hasVoted(uint256 proposalId, address account) public view virtual returns (bool); 214 | | 215 | | /** 216 | | * @dev Create a new proposal. Vote start after a delay specified by {IGovernor-votingDelay} and lasts for a 217 | | * duration specified by {IGovernor-votingPeriod}. 218 | | * 219 | | * Emits a {ProposalCreated} event. 220 | | */ 221 | | function propose( 222 | | address[] memory targets, 223 | | uint256[] memory values, 224 | | bytes[] memory calldatas, 225 | | string memory description 226 | | ) public virtual returns (uint256 proposalId); 227 | | 228 | | /** 229 | | * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the 230 | | * deadline to be reached. 231 | | * 232 | | * Emits a {ProposalExecuted} event. 233 | | * 234 | | * Note: some module can modify the requirements for execution, for example by adding an additional timelock. 235 | | */ 236 | | function execute( 237 | | address[] memory targets, 238 | | uint256[] memory values, 239 | | bytes[] memory calldatas, 240 | | bytes32 descriptionHash 241 | | ) public payable virtual returns (uint256 proposalId); 242 | | 243 | | /** 244 | | * @dev Cancel a proposal. A proposal is cancellable by the proposer, but only while it is Pending state, i.e. 245 | | * before the vote starts. 246 | | * 247 | | * Emits a {ProposalCanceled} event. 248 | | */ 249 | | function cancel( 250 | | address[] memory targets, 251 | | uint256[] memory values, 252 | | bytes[] memory calldatas, 253 | | bytes32 descriptionHash 254 | | ) public virtual returns (uint256 proposalId); 255 | | 256 | | /** 257 | | * @dev Cast a vote 258 | | * 259 | | * Emits a {VoteCast} event. 260 | | */ 261 | | function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance); 262 | | 263 | | /** 264 | | * @dev Cast a vote with a reason 265 | | * 266 | | * Emits a {VoteCast} event. 267 | | */ 268 | | function castVoteWithReason( 269 | | uint256 proposalId, 270 | | uint8 support, 271 | | string calldata reason 272 | | ) public virtual returns (uint256 balance); 273 | | 274 | | /** 275 | | * @dev Cast a vote with a reason and additional encoded parameters 276 | | * 277 | | * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params. 278 | | */ 279 | | function castVoteWithReasonAndParams( 280 | | uint256 proposalId, 281 | | uint8 support, 282 | | string calldata reason, 283 | | bytes memory params 284 | | ) public virtual returns (uint256 balance); 285 | | 286 | | /** 287 | | * @dev Cast a vote using the user's cryptographic signature. 288 | | * 289 | | * Emits a {VoteCast} event. 290 | | */ 291 | | function castVoteBySig( 292 | | uint256 proposalId, 293 | | uint8 support, 294 | | uint8 v, 295 | | bytes32 r, 296 | | bytes32 s 297 | | ) public virtual returns (uint256 balance); 298 | | 299 | | /** 300 | | * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature. 301 | | * 302 | | * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params. 303 | | */ 304 | | function castVoteWithReasonAndParamsBySig( 305 | | uint256 proposalId, 306 | | uint8 support, 307 | | string calldata reason, 308 | | bytes memory params, 309 | | uint8 v, 310 | | bytes32 r, 311 | | bytes32 s 312 | | ) public virtual returns (uint256 balance); 313 | | } 314 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/TimelockController.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/TimelockController.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../access/AccessControl.sol"; 7 | | import "../token/ERC721/IERC721Receiver.sol"; 8 | | import "../token/ERC1155/IERC1155Receiver.sol"; 9 | | 10 | | /** 11 | | * @dev Contract module which acts as a timelocked controller. When set as the 12 | | * owner of an `Ownable` smart contract, it enforces a timelock on all 13 | | * `onlyOwner` maintenance operations. This gives time for users of the 14 | | * controlled contract to exit before a potentially dangerous maintenance 15 | | * operation is applied. 16 | | * 17 | | * By default, this contract is self administered, meaning administration tasks 18 | | * have to go through the timelock process. The proposer (resp executor) role 19 | | * is in charge of proposing (resp executing) operations. A common use case is 20 | | * to position this {TimelockController} as the owner of a smart contract, with 21 | | * a multisig or a DAO as the sole proposer. 22 | | * 23 | | * _Available since v3.3._ 24 | | */ 25 | | contract TimelockController is AccessControl, IERC721Receiver, IERC1155Receiver { 26 | | bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE"); 27 | | bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); 28 | | bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); 29 | | bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); 30 | | uint256 internal constant _DONE_TIMESTAMP = uint256(1); 31 | | 32 | | mapping(bytes32 => uint256) private _timestamps; 33 | | uint256 private _minDelay; 34 | | 35 | | /** 36 | | * @dev Emitted when a call is scheduled as part of operation `id`. 37 | | */ 38 | | event CallScheduled( 39 | | bytes32 indexed id, 40 | | uint256 indexed index, 41 | | address target, 42 | | uint256 value, 43 | | bytes data, 44 | | bytes32 predecessor, 45 | | uint256 delay 46 | | ); 47 | | 48 | | /** 49 | | * @dev Emitted when a call is performed as part of operation `id`. 50 | | */ 51 | | event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data); 52 | | 53 | | /** 54 | | * @dev Emitted when new proposal is scheduled with non-zero salt. 55 | | */ 56 | | event CallSalt(bytes32 indexed id, bytes32 salt); 57 | | 58 | | /** 59 | | * @dev Emitted when operation `id` is cancelled. 60 | | */ 61 | | event Cancelled(bytes32 indexed id); 62 | | 63 | | /** 64 | | * @dev Emitted when the minimum delay for future operations is modified. 65 | | */ 66 | | event MinDelayChange(uint256 oldDuration, uint256 newDuration); 67 | | 68 | | /** 69 | | * @dev Initializes the contract with the following parameters: 70 | | * 71 | | * - `minDelay`: initial minimum delay for operations 72 | | * - `proposers`: accounts to be granted proposer and canceller roles 73 | | * - `executors`: accounts to be granted executor role 74 | | * - `admin`: optional account to be granted admin role; disable with zero address 75 | | * 76 | | * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment 77 | | * without being subject to delay, but this role should be subsequently renounced in favor of 78 | | * administration through timelocked proposals. Previous versions of this contract would assign 79 | | * this admin to the deployer automatically and should be renounced as well. 80 | | */ 81 | | constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) { 82 | | _setRoleAdmin(TIMELOCK_ADMIN_ROLE, TIMELOCK_ADMIN_ROLE); 83 | | _setRoleAdmin(PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE); 84 | | _setRoleAdmin(EXECUTOR_ROLE, TIMELOCK_ADMIN_ROLE); 85 | | _setRoleAdmin(CANCELLER_ROLE, TIMELOCK_ADMIN_ROLE); 86 | | 87 | | // self administration 88 | | _setupRole(TIMELOCK_ADMIN_ROLE, address(this)); 89 | | 90 | | // optional admin 91 | | if (admin != address(0)) { 92 | | _setupRole(TIMELOCK_ADMIN_ROLE, admin); 93 | | } 94 | | 95 | | // register proposers and cancellers 96 | | for (uint256 i = 0; i < proposers.length; ++i) { 97 | | _setupRole(PROPOSER_ROLE, proposers[i]); 98 | | _setupRole(CANCELLER_ROLE, proposers[i]); 99 | | } 100 | | 101 | | // register executors 102 | | for (uint256 i = 0; i < executors.length; ++i) { 103 | | _setupRole(EXECUTOR_ROLE, executors[i]); 104 | | } 105 | | 106 | | _minDelay = minDelay; 107 | | emit MinDelayChange(0, minDelay); 108 | | } 109 | | 110 | | /** 111 | | * @dev Modifier to make a function callable only by a certain role. In 112 | | * addition to checking the sender's role, `address(0)` 's role is also 113 | | * considered. Granting a role to `address(0)` is equivalent to enabling 114 | | * this role for everyone. 115 | | */ 116 | | modifier onlyRoleOrOpenRole(bytes32 role) { 117 | | if (!hasRole(role, address(0))) { 118 | | _checkRole(role, _msgSender()); 119 | | } 120 | | _; 121 | | } 122 | | 123 | | /** 124 | | * @dev Contract might receive/hold ETH as part of the maintenance process. 125 | | */ 126 | | receive() external payable {} 127 | | 128 | | /** 129 | | * @dev See {IERC165-supportsInterface}. 130 | | */ 131 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, AccessControl) returns (bool) { 132 | | return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); 133 | | } 134 | | 135 | | /** 136 | | * @dev Returns whether an id correspond to a registered operation. This 137 | | * includes both Pending, Ready and Done operations. 138 | | */ 139 | | function isOperation(bytes32 id) public view virtual returns (bool) { 140 | | return getTimestamp(id) > 0; 141 | | } 142 | | 143 | | /** 144 | | * @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready". 145 | | */ 146 | | function isOperationPending(bytes32 id) public view virtual returns (bool) { 147 | | return getTimestamp(id) > _DONE_TIMESTAMP; 148 | | } 149 | | 150 | | /** 151 | | * @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending". 152 | | */ 153 | | function isOperationReady(bytes32 id) public view virtual returns (bool) { 154 | | uint256 timestamp = getTimestamp(id); 155 | | return timestamp > _DONE_TIMESTAMP && timestamp <= block.timestamp; 156 | | } 157 | | 158 | | /** 159 | | * @dev Returns whether an operation is done or not. 160 | | */ 161 | | function isOperationDone(bytes32 id) public view virtual returns (bool) { 162 | | return getTimestamp(id) == _DONE_TIMESTAMP; 163 | | } 164 | | 165 | | /** 166 | | * @dev Returns the timestamp at which an operation becomes ready (0 for 167 | | * unset operations, 1 for done operations). 168 | | */ 169 | | function getTimestamp(bytes32 id) public view virtual returns (uint256) { 170 | | return _timestamps[id]; 171 | | } 172 | | 173 | | /** 174 | | * @dev Returns the minimum delay for an operation to become valid. 175 | | * 176 | | * This value can be changed by executing an operation that calls `updateDelay`. 177 | | */ 178 | | function getMinDelay() public view virtual returns (uint256) { 179 | | return _minDelay; 180 | | } 181 | | 182 | | /** 183 | | * @dev Returns the identifier of an operation containing a single 184 | | * transaction. 185 | | */ 186 | | function hashOperation( 187 | | address target, 188 | | uint256 value, 189 | | bytes calldata data, 190 | | bytes32 predecessor, 191 | | bytes32 salt 192 | | ) public pure virtual returns (bytes32) { 193 | | return keccak256(abi.encode(target, value, data, predecessor, salt)); 194 | | } 195 | | 196 | | /** 197 | | * @dev Returns the identifier of an operation containing a batch of 198 | | * transactions. 199 | | */ 200 | | function hashOperationBatch( 201 | | address[] calldata targets, 202 | | uint256[] calldata values, 203 | | bytes[] calldata payloads, 204 | | bytes32 predecessor, 205 | | bytes32 salt 206 | | ) public pure virtual returns (bytes32) { 207 | | return keccak256(abi.encode(targets, values, payloads, predecessor, salt)); 208 | | } 209 | | 210 | | /** 211 | | * @dev Schedule an operation containing a single transaction. 212 | | * 213 | | * Emits {CallSalt} if salt is nonzero, and {CallScheduled}. 214 | | * 215 | | * Requirements: 216 | | * 217 | | * - the caller must have the 'proposer' role. 218 | | */ 219 | | function schedule( 220 | | address target, 221 | | uint256 value, 222 | | bytes calldata data, 223 | | bytes32 predecessor, 224 | | bytes32 salt, 225 | | uint256 delay 226 | | ) public virtual onlyRole(PROPOSER_ROLE) { 227 | | bytes32 id = hashOperation(target, value, data, predecessor, salt); 228 | | _schedule(id, delay); 229 | | emit CallScheduled(id, 0, target, value, data, predecessor, delay); 230 | | if (salt != bytes32(0)) { 231 | | emit CallSalt(id, salt); 232 | | } 233 | | } 234 | | 235 | | /** 236 | | * @dev Schedule an operation containing a batch of transactions. 237 | | * 238 | | * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch. 239 | | * 240 | | * Requirements: 241 | | * 242 | | * - the caller must have the 'proposer' role. 243 | | */ 244 | | function scheduleBatch( 245 | | address[] calldata targets, 246 | | uint256[] calldata values, 247 | | bytes[] calldata payloads, 248 | | bytes32 predecessor, 249 | | bytes32 salt, 250 | | uint256 delay 251 | | ) public virtual onlyRole(PROPOSER_ROLE) { 252 | | require(targets.length == values.length, "TimelockController: length mismatch"); 253 | | require(targets.length == payloads.length, "TimelockController: length mismatch"); 254 | | 255 | | bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt); 256 | | _schedule(id, delay); 257 | | for (uint256 i = 0; i < targets.length; ++i) { 258 | | emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay); 259 | | } 260 | | if (salt != bytes32(0)) { 261 | | emit CallSalt(id, salt); 262 | | } 263 | | } 264 | | 265 | | /** 266 | | * @dev Schedule an operation that is to become valid after a given delay. 267 | | */ 268 | | function _schedule(bytes32 id, uint256 delay) private { 269 | | require(!isOperation(id), "TimelockController: operation already scheduled"); 270 | | require(delay >= getMinDelay(), "TimelockController: insufficient delay"); 271 | | _timestamps[id] = block.timestamp + delay; 272 | | } 273 | | 274 | | /** 275 | | * @dev Cancel an operation. 276 | | * 277 | | * Requirements: 278 | | * 279 | | * - the caller must have the 'canceller' role. 280 | | */ 281 | | function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) { 282 | | require(isOperationPending(id), "TimelockController: operation cannot be cancelled"); 283 | | delete _timestamps[id]; 284 | | 285 | | emit Cancelled(id); 286 | | } 287 | | 288 | | /** 289 | | * @dev Execute an (ready) operation containing a single transaction. 290 | | * 291 | | * Emits a {CallExecuted} event. 292 | | * 293 | | * Requirements: 294 | | * 295 | | * - the caller must have the 'executor' role. 296 | | */ 297 | | // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending, 298 | | // thus any modifications to the operation during reentrancy should be caught. 299 | | // slither-disable-next-line reentrancy-eth 300 | | function execute( 301 | | address target, 302 | | uint256 value, 303 | | bytes calldata payload, 304 | | bytes32 predecessor, 305 | | bytes32 salt 306 | | ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { 307 | | bytes32 id = hashOperation(target, value, payload, predecessor, salt); 308 | | 309 | | _beforeCall(id, predecessor); 310 | | _execute(target, value, payload); 311 | | emit CallExecuted(id, 0, target, value, payload); 312 | | _afterCall(id); 313 | | } 314 | | 315 | | /** 316 | | * @dev Execute an (ready) operation containing a batch of transactions. 317 | | * 318 | | * Emits one {CallExecuted} event per transaction in the batch. 319 | | * 320 | | * Requirements: 321 | | * 322 | | * - the caller must have the 'executor' role. 323 | | */ 324 | | // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending, 325 | | // thus any modifications to the operation during reentrancy should be caught. 326 | | // slither-disable-next-line reentrancy-eth 327 | | function executeBatch( 328 | | address[] calldata targets, 329 | | uint256[] calldata values, 330 | | bytes[] calldata payloads, 331 | | bytes32 predecessor, 332 | | bytes32 salt 333 | | ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) { 334 | | require(targets.length == values.length, "TimelockController: length mismatch"); 335 | | require(targets.length == payloads.length, "TimelockController: length mismatch"); 336 | | 337 | | bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt); 338 | | 339 | | _beforeCall(id, predecessor); 340 | | for (uint256 i = 0; i < targets.length; ++i) { 341 | | address target = targets[i]; 342 | | uint256 value = values[i]; 343 | | bytes calldata payload = payloads[i]; 344 | | _execute(target, value, payload); 345 | | emit CallExecuted(id, i, target, value, payload); 346 | | } 347 | | _afterCall(id); 348 | | } 349 | | 350 | | /** 351 | | * @dev Execute an operation's call. 352 | | */ 353 | | function _execute(address target, uint256 value, bytes calldata data) internal virtual { 354 | | (bool success, ) = target.call{value: value}(data); 355 | | require(success, "TimelockController: underlying transaction reverted"); 356 | | } 357 | | 358 | | /** 359 | | * @dev Checks before execution of an operation's calls. 360 | | */ 361 | | function _beforeCall(bytes32 id, bytes32 predecessor) private view { 362 | | require(isOperationReady(id), "TimelockController: operation is not ready"); 363 | | require(predecessor == bytes32(0) || isOperationDone(predecessor), "TimelockController: missing dependency"); 364 | | } 365 | | 366 | | /** 367 | | * @dev Checks after execution of an operation's calls. 368 | | */ 369 | | function _afterCall(bytes32 id) private { 370 | | require(isOperationReady(id), "TimelockController: operation is not ready"); 371 | | _timestamps[id] = _DONE_TIMESTAMP; 372 | | } 373 | | 374 | | /** 375 | | * @dev Changes the minimum timelock duration for future operations. 376 | | * 377 | | * Emits a {MinDelayChange} event. 378 | | * 379 | | * Requirements: 380 | | * 381 | | * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing 382 | | * an operation where the timelock is the target and the data is the ABI-encoded call to this function. 383 | | */ 384 | | function updateDelay(uint256 newDelay) external virtual { 385 | | require(msg.sender == address(this), "TimelockController: caller must be timelock"); 386 | | emit MinDelayChange(_minDelay, newDelay); 387 | | _minDelay = newDelay; 388 | | } 389 | | 390 | | /** 391 | | * @dev See {IERC721Receiver-onERC721Received}. 392 | | */ 393 | | function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) { 394 | | return this.onERC721Received.selector; 395 | | } 396 | | 397 | | /** 398 | | * @dev See {IERC1155Receiver-onERC1155Received}. 399 | | */ 400 | | function onERC1155Received( 401 | | address, 402 | | address, 403 | | uint256, 404 | | uint256, 405 | | bytes memory 406 | | ) public virtual override returns (bytes4) { 407 | | return this.onERC1155Received.selector; 408 | | } 409 | | 410 | | /** 411 | | * @dev See {IERC1155Receiver-onERC1155BatchReceived}. 412 | | */ 413 | | function onERC1155BatchReceived( 414 | | address, 415 | | address, 416 | | uint256[] memory, 417 | | uint256[] memory, 418 | | bytes memory 419 | | ) public virtual override returns (bytes4) { 420 | | return this.onERC1155BatchReceived.selector; 421 | | } 422 | | } 423 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/compatibility/GovernorCompatibilityBravo.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/compatibility/GovernorCompatibilityBravo.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../../utils/math/SafeCast.sol"; 7 | | import "../extensions/IGovernorTimelock.sol"; 8 | | import "../Governor.sol"; 9 | | import "./IGovernorCompatibilityBravo.sol"; 10 | | 11 | | /** 12 | | * @dev Compatibility layer that implements GovernorBravo compatibility on top of {Governor}. 13 | | * 14 | | * This compatibility layer includes a voting system and requires a {IGovernorTimelock} compatible module to be added 15 | | * through inheritance. It does not include token bindings, nor does it include any variable upgrade patterns. 16 | | * 17 | | * NOTE: When using this module, you may need to enable the Solidity optimizer to avoid hitting the contract size limit. 18 | | * 19 | | * _Available since v4.3._ 20 | | */ 21 | | abstract contract GovernorCompatibilityBravo is IGovernorTimelock, IGovernorCompatibilityBravo, Governor { 22 | | enum VoteType { 23 | | Against, 24 | | For, 25 | | Abstain 26 | | } 27 | | 28 | | struct ProposalDetails { 29 | | address proposer; 30 | | address[] targets; 31 | | uint256[] values; 32 | | string[] signatures; 33 | | bytes[] calldatas; 34 | | uint256 forVotes; 35 | | uint256 againstVotes; 36 | | uint256 abstainVotes; 37 | | mapping(address => Receipt) receipts; 38 | | bytes32 descriptionHash; 39 | | } 40 | | 41 | | mapping(uint256 => ProposalDetails) private _proposalDetails; 42 | | 43 | | // solhint-disable-next-line func-name-mixedcase 44 | | function COUNTING_MODE() public pure virtual override returns (string memory) { 45 | | return "support=bravo&quorum=bravo"; 46 | | } 47 | | 48 | | // ============================================== Proposal lifecycle ============================================== 49 | | /** 50 | | * @dev See {IGovernor-propose}. 51 | | */ 52 | | function propose( 53 | | address[] memory targets, 54 | | uint256[] memory values, 55 | | bytes[] memory calldatas, 56 | | string memory description 57 | | ) public virtual override(IGovernor, Governor) returns (uint256) { 58 | | // Stores the proposal details (if not already present) and executes the propose logic from the core. 59 | | _storeProposal(_msgSender(), targets, values, new string[](calldatas.length), calldatas, description); 60 | | return super.propose(targets, values, calldatas, description); 61 | | } 62 | | 63 | | /** 64 | | * @dev See {IGovernorCompatibilityBravo-propose}. 65 | | */ 66 | | function propose( 67 | | address[] memory targets, 68 | | uint256[] memory values, 69 | | string[] memory signatures, 70 | | bytes[] memory calldatas, 71 | | string memory description 72 | | ) public virtual override returns (uint256) { 73 | | require(signatures.length == calldatas.length, "GovernorBravo: invalid signatures length"); 74 | | // Stores the full proposal and fallback to the public (possibly overridden) propose. The fallback is done 75 | | // after the full proposal is stored, so the store operation included in the fallback will be skipped. Here we 76 | | // call `propose` and not `super.propose` to make sure if a child contract override `propose`, whatever code 77 | | // is added there is also executed when calling this alternative interface. 78 | | _storeProposal(_msgSender(), targets, values, signatures, calldatas, description); 79 | | return propose(targets, values, _encodeCalldata(signatures, calldatas), description); 80 | | } 81 | | 82 | | /** 83 | | * @dev See {IGovernorCompatibilityBravo-queue}. 84 | | */ 85 | | function queue(uint256 proposalId) public virtual override { 86 | | ( 87 | | address[] memory targets, 88 | | uint256[] memory values, 89 | | bytes[] memory calldatas, 90 | | bytes32 descriptionHash 91 | | ) = _getProposalParameters(proposalId); 92 | | 93 | | queue(targets, values, calldatas, descriptionHash); 94 | | } 95 | | 96 | | /** 97 | | * @dev See {IGovernorCompatibilityBravo-execute}. 98 | | */ 99 | | function execute(uint256 proposalId) public payable virtual override { 100 | | ( 101 | | address[] memory targets, 102 | | uint256[] memory values, 103 | | bytes[] memory calldatas, 104 | | bytes32 descriptionHash 105 | | ) = _getProposalParameters(proposalId); 106 | | 107 | | execute(targets, values, calldatas, descriptionHash); 108 | | } 109 | | 110 | | /** 111 | | * @dev Cancel a proposal with GovernorBravo logic. 112 | | */ 113 | | function cancel(uint256 proposalId) public virtual override { 114 | | ( 115 | | address[] memory targets, 116 | | uint256[] memory values, 117 | | bytes[] memory calldatas, 118 | | bytes32 descriptionHash 119 | | ) = _getProposalParameters(proposalId); 120 | | 121 | | cancel(targets, values, calldatas, descriptionHash); 122 | | } 123 | | 124 | | /** 125 | | * @dev Cancel a proposal with GovernorBravo logic. At any moment a proposal can be cancelled, either by the 126 | | * proposer, or by third parties if the proposer's voting power has dropped below the proposal threshold. 127 | | */ 128 | | function cancel( 129 | | address[] memory targets, 130 | | uint256[] memory values, 131 | | bytes[] memory calldatas, 132 | | bytes32 descriptionHash 133 | | ) public virtual override(IGovernor, Governor) returns (uint256) { 134 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); 135 | | address proposer = _proposalDetails[proposalId].proposer; 136 | | 137 | | require( 138 | | _msgSender() == proposer || getVotes(proposer, clock() - 1) < proposalThreshold(), 139 | | "GovernorBravo: proposer above threshold" 140 | | ); 141 | | 142 | | return _cancel(targets, values, calldatas, descriptionHash); 143 | | } 144 | | 145 | | /** 146 | | * @dev Encodes calldatas with optional function signature. 147 | | */ 148 | | function _encodeCalldata( 149 | | string[] memory signatures, 150 | | bytes[] memory calldatas 151 | | ) private pure returns (bytes[] memory) { 152 | | bytes[] memory fullcalldatas = new bytes[](calldatas.length); 153 | | for (uint256 i = 0; i < fullcalldatas.length; ++i) { 154 | | fullcalldatas[i] = bytes(signatures[i]).length == 0 155 | | ? calldatas[i] 156 | | : abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), calldatas[i]); 157 | | } 158 | | 159 | | return fullcalldatas; 160 | | } 161 | | 162 | | /** 163 | | * @dev Retrieve proposal parameters by id, with fully encoded calldatas. 164 | | */ 165 | | function _getProposalParameters( 166 | | uint256 proposalId 167 | | ) 168 | | private 169 | | view 170 | | returns (address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) 171 | | { 172 | | ProposalDetails storage details = _proposalDetails[proposalId]; 173 | | return ( 174 | | details.targets, 175 | | details.values, 176 | | _encodeCalldata(details.signatures, details.calldatas), 177 | | details.descriptionHash 178 | | ); 179 | | } 180 | | 181 | | /** 182 | | * @dev Store proposal metadata (if not already present) for later lookup. 183 | | */ 184 | | function _storeProposal( 185 | | address proposer, 186 | | address[] memory targets, 187 | | uint256[] memory values, 188 | | string[] memory signatures, 189 | | bytes[] memory calldatas, 190 | | string memory description 191 | | ) private { 192 | | bytes32 descriptionHash = keccak256(bytes(description)); 193 | | uint256 proposalId = hashProposal(targets, values, _encodeCalldata(signatures, calldatas), descriptionHash); 194 | | 195 | | ProposalDetails storage details = _proposalDetails[proposalId]; 196 | | if (details.descriptionHash == bytes32(0)) { 197 | | details.proposer = proposer; 198 | | details.targets = targets; 199 | | details.values = values; 200 | | details.signatures = signatures; 201 | | details.calldatas = calldatas; 202 | | details.descriptionHash = descriptionHash; 203 | | } 204 | | } 205 | | 206 | | // ==================================================== Views ===================================================== 207 | | /** 208 | | * @dev See {IGovernorCompatibilityBravo-proposals}. 209 | | */ 210 | | function proposals( 211 | | uint256 proposalId 212 | | ) 213 | | public 214 | | view 215 | | virtual 216 | | override 217 | | returns ( 218 | | uint256 id, 219 | | address proposer, 220 | | uint256 eta, 221 | | uint256 startBlock, 222 | | uint256 endBlock, 223 | | uint256 forVotes, 224 | | uint256 againstVotes, 225 | | uint256 abstainVotes, 226 | | bool canceled, 227 | | bool executed 228 | | ) 229 | | { 230 | | id = proposalId; 231 | | eta = proposalEta(proposalId); 232 | | startBlock = proposalSnapshot(proposalId); 233 | | endBlock = proposalDeadline(proposalId); 234 | | 235 | | ProposalDetails storage details = _proposalDetails[proposalId]; 236 | | proposer = details.proposer; 237 | | forVotes = details.forVotes; 238 | | againstVotes = details.againstVotes; 239 | | abstainVotes = details.abstainVotes; 240 | | 241 | | ProposalState currentState = state(proposalId); 242 | | canceled = currentState == ProposalState.Canceled; 243 | | executed = currentState == ProposalState.Executed; 244 | | } 245 | | 246 | | /** 247 | | * @dev See {IGovernorCompatibilityBravo-getActions}. 248 | | */ 249 | | function getActions( 250 | | uint256 proposalId 251 | | ) 252 | | public 253 | | view 254 | | virtual 255 | | override 256 | | returns ( 257 | | address[] memory targets, 258 | | uint256[] memory values, 259 | | string[] memory signatures, 260 | | bytes[] memory calldatas 261 | | ) 262 | | { 263 | | ProposalDetails storage details = _proposalDetails[proposalId]; 264 | | return (details.targets, details.values, details.signatures, details.calldatas); 265 | | } 266 | | 267 | | /** 268 | | * @dev See {IGovernorCompatibilityBravo-getReceipt}. 269 | | */ 270 | | function getReceipt(uint256 proposalId, address voter) public view virtual override returns (Receipt memory) { 271 | | return _proposalDetails[proposalId].receipts[voter]; 272 | | } 273 | | 274 | | /** 275 | | * @dev See {IGovernorCompatibilityBravo-quorumVotes}. 276 | | */ 277 | | function quorumVotes() public view virtual override returns (uint256) { 278 | | return quorum(clock() - 1); 279 | | } 280 | | 281 | | // ==================================================== Voting ==================================================== 282 | | /** 283 | | * @dev See {IGovernor-hasVoted}. 284 | | */ 285 | | function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) { 286 | | return _proposalDetails[proposalId].receipts[account].hasVoted; 287 | | } 288 | | 289 | | /** 290 | | * @dev See {Governor-_quorumReached}. In this module, only forVotes count toward the quorum. 291 | | */ 292 | | function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) { 293 | | ProposalDetails storage details = _proposalDetails[proposalId]; 294 | | return quorum(proposalSnapshot(proposalId)) <= details.forVotes; 295 | | } 296 | | 297 | | /** 298 | | * @dev See {Governor-_voteSucceeded}. In this module, the forVotes must be strictly over the againstVotes. 299 | | */ 300 | | function _voteSucceeded(uint256 proposalId) internal view virtual override returns (bool) { 301 | | ProposalDetails storage details = _proposalDetails[proposalId]; 302 | | return details.forVotes > details.againstVotes; 303 | | } 304 | | 305 | | /** 306 | | * @dev See {Governor-_countVote}. In this module, the support follows Governor Bravo. 307 | | */ 308 | | function _countVote( 309 | | uint256 proposalId, 310 | | address account, 311 | | uint8 support, 312 | | uint256 weight, 313 | | bytes memory // params 314 | | ) internal virtual override { 315 | | ProposalDetails storage details = _proposalDetails[proposalId]; 316 | | Receipt storage receipt = details.receipts[account]; 317 | | 318 | | require(!receipt.hasVoted, "GovernorCompatibilityBravo: vote already cast"); 319 | | receipt.hasVoted = true; 320 | | receipt.support = support; 321 | | receipt.votes = SafeCast.toUint96(weight); 322 | | 323 | | if (support == uint8(VoteType.Against)) { 324 | | details.againstVotes += weight; 325 | | } else if (support == uint8(VoteType.For)) { 326 | | details.forVotes += weight; 327 | | } else if (support == uint8(VoteType.Abstain)) { 328 | | details.abstainVotes += weight; 329 | | } else { 330 | | revert("GovernorCompatibilityBravo: invalid vote type"); 331 | | } 332 | | } 333 | | } 334 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/compatibility/IGovernorCompatibilityBravo.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/compatibility/IGovernorCompatibilityBravo.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../IGovernor.sol"; 7 | | 8 | | /** 9 | | * @dev Interface extension that adds missing functions to the {Governor} core to provide `GovernorBravo` compatibility. 10 | | * 11 | | * _Available since v4.3._ 12 | | */ 13 | | abstract contract IGovernorCompatibilityBravo is IGovernor { 14 | | /** 15 | | * @dev Proposal structure from Compound Governor Bravo. Not actually used by the compatibility layer, as 16 | | * {{proposal}} returns a very different structure. 17 | | */ 18 | | struct Proposal { 19 | | uint256 id; 20 | | address proposer; 21 | | uint256 eta; 22 | | address[] targets; 23 | | uint256[] values; 24 | | string[] signatures; 25 | | bytes[] calldatas; 26 | | uint256 startBlock; 27 | | uint256 endBlock; 28 | | uint256 forVotes; 29 | | uint256 againstVotes; 30 | | uint256 abstainVotes; 31 | | bool canceled; 32 | | bool executed; 33 | | mapping(address => Receipt) receipts; 34 | | } 35 | | 36 | | /** 37 | | * @dev Receipt structure from Compound Governor Bravo 38 | | */ 39 | | struct Receipt { 40 | | bool hasVoted; 41 | | uint8 support; 42 | | uint96 votes; 43 | | } 44 | | 45 | | /** 46 | | * @dev Part of the Governor Bravo's interface. 47 | | */ 48 | | function quorumVotes() public view virtual returns (uint256); 49 | | 50 | | /** 51 | | * @dev Part of the Governor Bravo's interface: _"The official record of all proposals ever proposed"_. 52 | | */ 53 | | function proposals( 54 | | uint256 55 | | ) 56 | | public 57 | | view 58 | | virtual 59 | | returns ( 60 | | uint256 id, 61 | | address proposer, 62 | | uint256 eta, 63 | | uint256 startBlock, 64 | | uint256 endBlock, 65 | | uint256 forVotes, 66 | | uint256 againstVotes, 67 | | uint256 abstainVotes, 68 | | bool canceled, 69 | | bool executed 70 | | ); 71 | | 72 | | /** 73 | | * @dev Part of the Governor Bravo's interface: _"Function used to propose a new proposal"_. 74 | | */ 75 | | function propose( 76 | | address[] memory targets, 77 | | uint256[] memory values, 78 | | string[] memory signatures, 79 | | bytes[] memory calldatas, 80 | | string memory description 81 | | ) public virtual returns (uint256); 82 | | 83 | | /** 84 | | * @dev Part of the Governor Bravo's interface: _"Queues a proposal of state succeeded"_. 85 | | */ 86 | | function queue(uint256 proposalId) public virtual; 87 | | 88 | | /** 89 | | * @dev Part of the Governor Bravo's interface: _"Executes a queued proposal if eta has passed"_. 90 | | */ 91 | | function execute(uint256 proposalId) public payable virtual; 92 | | 93 | | /** 94 | | * @dev Cancels a proposal only if the sender is the proposer or the proposer delegates' voting power dropped below the proposal threshold. 95 | | */ 96 | | function cancel(uint256 proposalId) public virtual; 97 | | 98 | | /** 99 | | * @dev Part of the Governor Bravo's interface: _"Gets actions of a proposal"_. 100 | | */ 101 | | function getActions( 102 | | uint256 proposalId 103 | | ) 104 | | public 105 | | view 106 | | virtual 107 | | returns ( 108 | | address[] memory targets, 109 | | uint256[] memory values, 110 | | string[] memory signatures, 111 | | bytes[] memory calldatas 112 | | ); 113 | | 114 | | /** 115 | | * @dev Part of the Governor Bravo's interface: _"Gets the receipt for a voter on a given proposal"_. 116 | | */ 117 | | function getReceipt(uint256 proposalId, address voter) public view virtual returns (Receipt memory); 118 | | } 119 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorSettings.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorSettings.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../Governor.sol"; 7 | | 8 | | /** 9 | | * @dev Extension of {Governor} for settings updatable through governance. 10 | | * 11 | | * _Available since v4.4._ 12 | | */ 13 | | abstract contract GovernorSettings is Governor { 14 | | uint256 private _votingDelay; 15 | | uint256 private _votingPeriod; 16 | | uint256 private _proposalThreshold; 17 | | 18 | | event VotingDelaySet(uint256 oldVotingDelay, uint256 newVotingDelay); 19 | | event VotingPeriodSet(uint256 oldVotingPeriod, uint256 newVotingPeriod); 20 | | event ProposalThresholdSet(uint256 oldProposalThreshold, uint256 newProposalThreshold); 21 | | 22 | | /** 23 | | * @dev Initialize the governance parameters. 24 | | */ 25 | | constructor(uint256 initialVotingDelay, uint256 initialVotingPeriod, uint256 initialProposalThreshold) { 26 | | _setVotingDelay(initialVotingDelay); 27 | | _setVotingPeriod(initialVotingPeriod); 28 | | _setProposalThreshold(initialProposalThreshold); 29 | | } 30 | | 31 | | /** 32 | | * @dev See {IGovernor-votingDelay}. 33 | | */ 34 | | function votingDelay() public view virtual override returns (uint256) { 35 | | return _votingDelay; 36 | | } 37 | | 38 | | /** 39 | | * @dev See {IGovernor-votingPeriod}. 40 | | */ 41 | | function votingPeriod() public view virtual override returns (uint256) { 42 | | return _votingPeriod; 43 | | } 44 | | 45 | | /** 46 | | * @dev See {Governor-proposalThreshold}. 47 | | */ 48 | | function proposalThreshold() public view virtual override returns (uint256) { 49 | | return _proposalThreshold; 50 | | } 51 | | 52 | | /** 53 | | * @dev Update the voting delay. This operation can only be performed through a governance proposal. 54 | | * 55 | | * Emits a {VotingDelaySet} event. 56 | | */ 57 | | function setVotingDelay(uint256 newVotingDelay) public virtual onlyGovernance { 58 | | _setVotingDelay(newVotingDelay); 59 | | } 60 | | 61 | | /** 62 | | * @dev Update the voting period. This operation can only be performed through a governance proposal. 63 | | * 64 | | * Emits a {VotingPeriodSet} event. 65 | | */ 66 | | function setVotingPeriod(uint256 newVotingPeriod) public virtual onlyGovernance { 67 | | _setVotingPeriod(newVotingPeriod); 68 | | } 69 | | 70 | | /** 71 | | * @dev Update the proposal threshold. This operation can only be performed through a governance proposal. 72 | | * 73 | | * Emits a {ProposalThresholdSet} event. 74 | | */ 75 | | function setProposalThreshold(uint256 newProposalThreshold) public virtual onlyGovernance { 76 | | _setProposalThreshold(newProposalThreshold); 77 | | } 78 | | 79 | | /** 80 | | * @dev Internal setter for the voting delay. 81 | | * 82 | | * Emits a {VotingDelaySet} event. 83 | | */ 84 | | function _setVotingDelay(uint256 newVotingDelay) internal virtual { 85 | | emit VotingDelaySet(_votingDelay, newVotingDelay); 86 | | _votingDelay = newVotingDelay; 87 | | } 88 | | 89 | | /** 90 | | * @dev Internal setter for the voting period. 91 | | * 92 | | * Emits a {VotingPeriodSet} event. 93 | | */ 94 | | function _setVotingPeriod(uint256 newVotingPeriod) internal virtual { 95 | | // voting period must be at least one block long 96 | | require(newVotingPeriod > 0, "GovernorSettings: voting period too low"); 97 | | emit VotingPeriodSet(_votingPeriod, newVotingPeriod); 98 | | _votingPeriod = newVotingPeriod; 99 | | } 100 | | 101 | | /** 102 | | * @dev Internal setter for the proposal threshold. 103 | | * 104 | | * Emits a {ProposalThresholdSet} event. 105 | | */ 106 | | function _setProposalThreshold(uint256 newProposalThreshold) internal virtual { 107 | | emit ProposalThresholdSet(_proposalThreshold, newProposalThreshold); 108 | | _proposalThreshold = newProposalThreshold; 109 | | } 110 | | } 111 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorTimelockControl.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./IGovernorTimelock.sol"; 7 | | import "../Governor.sol"; 8 | | import "../TimelockController.sol"; 9 | | 10 | | /** 11 | | * @dev Extension of {Governor} that binds the execution process to an instance of {TimelockController}. This adds a 12 | | * delay, enforced by the {TimelockController} to all successful proposal (in addition to the voting duration). The 13 | | * {Governor} needs the proposer (and ideally the executor) roles for the {Governor} to work properly. 14 | | * 15 | | * Using this model means the proposal will be operated by the {TimelockController} and not by the {Governor}. Thus, 16 | | * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be 17 | | * inaccessible. 18 | | * 19 | | * WARNING: Setting up the TimelockController to have additional proposers besides the governor is very risky, as it 20 | | * grants them powers that they must be trusted or known not to use: 1) {onlyGovernance} functions like {relay} are 21 | | * available to them through the timelock, and 2) approved governance proposals can be blocked by them, effectively 22 | | * executing a Denial of Service attack. This risk will be mitigated in a future release. 23 | | * 24 | | * _Available since v4.3._ 25 | | */ 26 | | abstract contract GovernorTimelockControl is IGovernorTimelock, Governor { 27 | | TimelockController private _timelock; 28 | | mapping(uint256 => bytes32) private _timelockIds; 29 | | 30 | | /** 31 | | * @dev Emitted when the timelock controller used for proposal execution is modified. 32 | | */ 33 | | event TimelockChange(address oldTimelock, address newTimelock); 34 | | 35 | | /** 36 | | * @dev Set the timelock. 37 | | */ 38 | | constructor(TimelockController timelockAddress) { 39 | | _updateTimelock(timelockAddress); 40 | | } 41 | | 42 | | /** 43 | | * @dev See {IERC165-supportsInterface}. 44 | | */ 45 | | function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, Governor) returns (bool) { 46 | | return interfaceId == type(IGovernorTimelock).interfaceId || super.supportsInterface(interfaceId); 47 | | } 48 | | 49 | | /** 50 | | * @dev Overridden version of the {Governor-state} function with added support for the `Queued` state. 51 | | */ 52 | | function state(uint256 proposalId) public view virtual override(IGovernor, Governor) returns (ProposalState) { 53 | | ProposalState currentState = super.state(proposalId); 54 | | 55 | | if (currentState != ProposalState.Succeeded) { 56 | | return currentState; 57 | | } 58 | | 59 | | // core tracks execution, so we just have to check if successful proposal have been queued. 60 | | bytes32 queueid = _timelockIds[proposalId]; 61 | | if (queueid == bytes32(0)) { 62 | | return currentState; 63 | | } else if (_timelock.isOperationDone(queueid)) { 64 | | return ProposalState.Executed; 65 | | } else if (_timelock.isOperationPending(queueid)) { 66 | | return ProposalState.Queued; 67 | | } else { 68 | | return ProposalState.Canceled; 69 | | } 70 | | } 71 | | 72 | | /** 73 | | * @dev Public accessor to check the address of the timelock 74 | | */ 75 | | function timelock() public view virtual override returns (address) { 76 | | return address(_timelock); 77 | | } 78 | | 79 | | /** 80 | | * @dev Public accessor to check the eta of a queued proposal 81 | | */ 82 | | function proposalEta(uint256 proposalId) public view virtual override returns (uint256) { 83 | | uint256 eta = _timelock.getTimestamp(_timelockIds[proposalId]); 84 | | return eta == 1 ? 0 : eta; // _DONE_TIMESTAMP (1) should be replaced with a 0 value 85 | | } 86 | | 87 | | /** 88 | | * @dev Function to queue a proposal to the timelock. 89 | | */ 90 | | function queue( 91 | | address[] memory targets, 92 | | uint256[] memory values, 93 | | bytes[] memory calldatas, 94 | | bytes32 descriptionHash 95 | | ) public virtual override returns (uint256) { 96 | | uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash); 97 | | 98 | | require(state(proposalId) == ProposalState.Succeeded, "Governor: proposal not successful"); 99 | | 100 | | uint256 delay = _timelock.getMinDelay(); 101 | | _timelockIds[proposalId] = _timelock.hashOperationBatch(targets, values, calldatas, 0, descriptionHash); 102 | | _timelock.scheduleBatch(targets, values, calldatas, 0, descriptionHash, delay); 103 | | 104 | | emit ProposalQueued(proposalId, block.timestamp + delay); 105 | | 106 | | return proposalId; 107 | | } 108 | | 109 | | /** 110 | | * @dev Overridden execute function that run the already queued proposal through the timelock. 111 | | */ 112 | | function _execute( 113 | | uint256 /* proposalId */, 114 | | address[] memory targets, 115 | | uint256[] memory values, 116 | | bytes[] memory calldatas, 117 | | bytes32 descriptionHash 118 | | ) internal virtual override { 119 | | _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash); 120 | | } 121 | | 122 | | /** 123 | | * @dev Overridden version of the {Governor-_cancel} function to cancel the timelocked proposal if it as already 124 | | * been queued. 125 | | */ 126 | | // This function can reenter through the external call to the timelock, but we assume the timelock is trusted and 127 | | // well behaved (according to TimelockController) and this will not happen. 128 | | // slither-disable-next-line reentrancy-no-eth 129 | | function _cancel( 130 | | address[] memory targets, 131 | | uint256[] memory values, 132 | | bytes[] memory calldatas, 133 | | bytes32 descriptionHash 134 | | ) internal virtual override returns (uint256) { 135 | | uint256 proposalId = super._cancel(targets, values, calldatas, descriptionHash); 136 | | 137 | | if (_timelockIds[proposalId] != 0) { 138 | | _timelock.cancel(_timelockIds[proposalId]); 139 | | delete _timelockIds[proposalId]; 140 | | } 141 | | 142 | | return proposalId; 143 | | } 144 | | 145 | | /** 146 | | * @dev Address through which the governor executes action. In this case, the timelock. 147 | | */ 148 | | function _executor() internal view virtual override returns (address) { 149 | | return address(_timelock); 150 | | } 151 | | 152 | | /** 153 | | * @dev Public endpoint to update the underlying timelock instance. Restricted to the timelock itself, so updates 154 | | * must be proposed, scheduled, and executed through governance proposals. 155 | | * 156 | | * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals. 157 | | */ 158 | | function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance { 159 | | _updateTimelock(newTimelock); 160 | | } 161 | | 162 | | function _updateTimelock(TimelockController newTimelock) private { 163 | | emit TimelockChange(address(_timelock), address(newTimelock)); 164 | | _timelock = newTimelock; 165 | | } 166 | | } 167 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotes.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorVotes.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../Governor.sol"; 7 | | import "../../interfaces/IERC5805.sol"; 8 | | 9 | | /** 10 | | * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token, or since v4.5 an {ERC721Votes} token. 11 | | * 12 | | * _Available since v4.3._ 13 | | */ 14 | | abstract contract GovernorVotes is Governor { 15 | | IERC5805 public immutable token; 16 | | 17 | | constructor(IVotes tokenAddress) { 18 | | token = IERC5805(address(tokenAddress)); 19 | | } 20 | | 21 | | /** 22 | | * @dev Clock (as specified in EIP-6372) is set to match the token's clock. Fallback to block numbers if the token 23 | | * does not implement EIP-6372. 24 | | */ 25 | | function clock() public view virtual override returns (uint48) { 26 | | try token.clock() returns (uint48 timepoint) { 27 | | return timepoint; 28 | | } catch { 29 | | return SafeCast.toUint48(block.number); 30 | | } 31 | | } 32 | | 33 | | /** 34 | | * @dev Machine-readable description of the clock as specified in EIP-6372. 35 | | */ 36 | | // solhint-disable-next-line func-name-mixedcase 37 | | function CLOCK_MODE() public view virtual override returns (string memory) { 38 | | try token.CLOCK_MODE() returns (string memory clockmode) { 39 | | return clockmode; 40 | | } catch { 41 | | return "mode=blocknumber&from=default"; 42 | | } 43 | | } 44 | | 45 | | /** 46 | | * Read the voting weight from the token's built in snapshot mechanism (see {Governor-_getVotes}). 47 | | */ 48 | | function _getVotes( 49 | | address account, 50 | | uint256 timepoint, 51 | | bytes memory /*params*/ 52 | | ) internal view virtual override returns (uint256) { 53 | | return token.getPastVotes(account, timepoint); 54 | | } 55 | | } 56 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/extensions/GovernorVotesQuorumFraction.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./GovernorVotes.sol"; 7 | | import "../../utils/Checkpoints.sol"; 8 | | import "../../utils/math/SafeCast.sol"; 9 | | 10 | | /** 11 | | * @dev Extension of {Governor} for voting weight extraction from an {ERC20Votes} token and a quorum expressed as a 12 | | * fraction of the total supply. 13 | | * 14 | | * _Available since v4.3._ 15 | | */ 16 | | abstract contract GovernorVotesQuorumFraction is GovernorVotes { 17 | | using Checkpoints for Checkpoints.Trace224; 18 | | 19 | | uint256 private _quorumNumerator; // DEPRECATED in favor of _quorumNumeratorHistory 20 | | 21 | | /// @custom:oz-retyped-from Checkpoints.History 22 | | Checkpoints.Trace224 private _quorumNumeratorHistory; 23 | | 24 | | event QuorumNumeratorUpdated(uint256 oldQuorumNumerator, uint256 newQuorumNumerator); 25 | | 26 | | /** 27 | | * @dev Initialize quorum as a fraction of the token's total supply. 28 | | * 29 | | * The fraction is specified as `numerator / denominator`. By default the denominator is 100, so quorum is 30 | | * specified as a percent: a numerator of 10 corresponds to quorum being 10% of total supply. The denominator can be 31 | | * customized by overriding {quorumDenominator}. 32 | | */ 33 | | constructor(uint256 quorumNumeratorValue) { 34 | | _updateQuorumNumerator(quorumNumeratorValue); 35 | | } 36 | | 37 | | /** 38 | | * @dev Returns the current quorum numerator. See {quorumDenominator}. 39 | | */ 40 | | function quorumNumerator() public view virtual returns (uint256) { 41 | | return _quorumNumeratorHistory._checkpoints.length == 0 ? _quorumNumerator : _quorumNumeratorHistory.latest(); 42 | | } 43 | | 44 | | /** 45 | | * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}. 46 | | */ 47 | | function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) { 48 | | // If history is empty, fallback to old storage 49 | | uint256 length = _quorumNumeratorHistory._checkpoints.length; 50 | | if (length == 0) { 51 | | return _quorumNumerator; 52 | | } 53 | | 54 | | // Optimistic search, check the latest checkpoint 55 | | Checkpoints.Checkpoint224 memory latest = _quorumNumeratorHistory._checkpoints[length - 1]; 56 | | if (latest._key <= timepoint) { 57 | | return latest._value; 58 | | } 59 | | 60 | | // Otherwise, do the binary search 61 | | return _quorumNumeratorHistory.upperLookupRecent(SafeCast.toUint32(timepoint)); 62 | | } 63 | | 64 | | /** 65 | | * @dev Returns the quorum denominator. Defaults to 100, but may be overridden. 66 | | */ 67 | | function quorumDenominator() public view virtual returns (uint256) { 68 | | return 100; 69 | | } 70 | | 71 | | /** 72 | | * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`. 73 | | */ 74 | | function quorum(uint256 timepoint) public view virtual override returns (uint256) { 75 | | return (token.getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator(); 76 | | } 77 | | 78 | | /** 79 | | * @dev Changes the quorum numerator. 80 | | * 81 | | * Emits a {QuorumNumeratorUpdated} event. 82 | | * 83 | | * Requirements: 84 | | * 85 | | * - Must be called through a governance proposal. 86 | | * - New numerator must be smaller or equal to the denominator. 87 | | */ 88 | | function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance { 89 | | _updateQuorumNumerator(newQuorumNumerator); 90 | | } 91 | | 92 | | /** 93 | | * @dev Changes the quorum numerator. 94 | | * 95 | | * Emits a {QuorumNumeratorUpdated} event. 96 | | * 97 | | * Requirements: 98 | | * 99 | | * - New numerator must be smaller or equal to the denominator. 100 | | */ 101 | | function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual { 102 | | require( 103 | | newQuorumNumerator <= quorumDenominator(), 104 | | "GovernorVotesQuorumFraction: quorumNumerator over quorumDenominator" 105 | | ); 106 | | 107 | | uint256 oldQuorumNumerator = quorumNumerator(); 108 | | 109 | | // Make sure we keep track of the original numerator in contracts upgraded from a version without checkpoints. 110 | | if (oldQuorumNumerator != 0 && _quorumNumeratorHistory._checkpoints.length == 0) { 111 | | _quorumNumeratorHistory._checkpoints.push( 112 | | Checkpoints.Checkpoint224({_key: 0, _value: SafeCast.toUint224(oldQuorumNumerator)}) 113 | | ); 114 | | } 115 | | 116 | | // Set new quorum for future proposals 117 | | _quorumNumeratorHistory.push(SafeCast.toUint32(clock()), SafeCast.toUint224(newQuorumNumerator)); 118 | | 119 | | emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator); 120 | | } 121 | | } 122 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/extensions/IGovernorTimelock.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (governance/extensions/IGovernorTimelock.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../IGovernor.sol"; 7 | | 8 | | /** 9 | | * @dev Extension of the {IGovernor} for timelock supporting modules. 10 | | * 11 | | * _Available since v4.3._ 12 | | */ 13 | | abstract contract IGovernorTimelock is IGovernor { 14 | | event ProposalQueued(uint256 proposalId, uint256 eta); 15 | | 16 | | function timelock() public view virtual returns (address); 17 | | 18 | | function proposalEta(uint256 proposalId) public view virtual returns (uint256); 19 | | 20 | | function queue( 21 | | address[] memory targets, 22 | | uint256[] memory values, 23 | | bytes[] memory calldatas, 24 | | bytes32 descriptionHash 25 | | ) public virtual returns (uint256 proposalId); 26 | | } 27 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol) 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. 7 | | * 8 | | * _Available since v4.5._ 9 | | */ 10 | | interface IVotes { 11 | | /** 12 | | * @dev Emitted when an account changes their delegate. 13 | | */ 14 | | event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); 15 | | 16 | | /** 17 | | * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. 18 | | */ 19 | | event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); 20 | | 21 | | /** 22 | | * @dev Returns the current amount of votes that `account` has. 23 | | */ 24 | | function getVotes(address account) external view returns (uint256); 25 | | 26 | | /** 27 | | * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is 28 | | * configured to use block numbers, this will return the value at the end of the corresponding block. 29 | | */ 30 | | function getPastVotes(address account, uint256 timepoint) external view returns (uint256); 31 | | 32 | | /** 33 | | * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is 34 | | * configured to use block numbers, this will return the value at the end of the corresponding block. 35 | | * 36 | | * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. 37 | | * Votes that have not been delegated are still part of total supply, even though they would not participate in a 38 | | * vote. 39 | | */ 40 | | function getPastTotalSupply(uint256 timepoint) external view returns (uint256); 41 | | 42 | | /** 43 | | * @dev Returns the delegate that `account` has chosen. 44 | | */ 45 | | function delegates(address account) external view returns (address); 46 | | 47 | | /** 48 | | * @dev Delegates votes from the sender to `delegatee`. 49 | | */ 50 | | function delegate(address delegatee) external; 51 | | 52 | | /** 53 | | * @dev Delegates votes from signer to `delegatee`. 54 | | */ 55 | | function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; 56 | | } 57 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC165.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../utils/introspection/IERC165.sol"; 7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC1967.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. 8 | | * 9 | | * _Available since v4.8.3._ 10 | | */ 11 | | interface IERC1967 { 12 | | /** 13 | | * @dev Emitted when the implementation is upgraded. 14 | | */ 15 | | event Upgraded(address indexed implementation); 16 | | 17 | | /** 18 | | * @dev Emitted when the admin account has changed. 19 | | */ 20 | | event AdminChanged(address previousAdmin, address newAdmin); 21 | | 22 | | /** 23 | | * @dev Emitted when the beacon is changed. 24 | | */ 25 | | event BeaconUpgraded(address indexed beacon); 26 | | } 27 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | interface IERC5267 { 7 | | /** 8 | | * @dev MAY be emitted to signal that the domain could have changed. 9 | | */ 10 | | event EIP712DomainChanged(); 11 | | 12 | | /** 13 | | * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 14 | | * signature. 15 | | */ 16 | | function eip712Domain() 17 | | external 18 | | view 19 | | returns ( 20 | | bytes1 fields, 21 | | string memory name, 22 | | string memory version, 23 | | uint256 chainId, 24 | | address verifyingContract, 25 | | bytes32 salt, 26 | | uint256[] memory extensions 27 | | ); 28 | | } 29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5805.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../governance/utils/IVotes.sol"; 7 | | import "./IERC6372.sol"; 8 | | 9 | | interface IERC5805 is IERC6372, IVotes {} 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | interface IERC6372 { 7 | | /** 8 | | * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). 9 | | */ 10 | | function clock() external view returns (uint48); 11 | | 12 | | /** 13 | | * @dev Description of the clock 14 | | */ 15 | | // solhint-disable-next-line func-name-mixedcase 16 | | function CLOCK_MODE() external view returns (string memory); 17 | | } 18 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified 8 | | * proxy whose upgrades are fully controlled by the current implementation. 9 | | */ 10 | | interface IERC1822Proxiable { 11 | | /** 12 | | * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation 13 | | * address. 14 | | * 15 | | * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks 16 | | * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this 17 | | * function revert if invoked through a proxy. 18 | | */ 19 | | function proxiableUUID() external view returns (bytes32); 20 | | } 21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../Proxy.sol"; 7 | | import "./ERC1967Upgrade.sol"; 8 | | 9 | | /** 10 | | * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an 11 | | * implementation address that can be changed. This address is stored in storage in the location specified by 12 | | * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the 13 | | * implementation behind the proxy. 14 | | */ 15 | | contract ERC1967Proxy is Proxy, ERC1967Upgrade { 16 | | /** 17 | | * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. 18 | | * 19 | | * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded 20 | | * function call, and allows initializing the storage of the proxy like a Solidity constructor. 21 | | */ 22 | | constructor(address _logic, bytes memory _data) payable { 23 | | _upgradeToAndCall(_logic, _data, false); 24 | | } 25 | | 26 | | /** 27 | | * @dev Returns the current implementation address. 28 | | */ 29 | * | function _implementation() internal view virtual override returns (address impl) { 30 | * | return ERC1967Upgrade._getImplementation(); 31 | | } 32 | | } 33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) 3 | | 4 | | pragma solidity ^0.8.2; 5 | | 6 | | import "../beacon/IBeacon.sol"; 7 | | import "../../interfaces/IERC1967.sol"; 8 | | import "../../interfaces/draft-IERC1822.sol"; 9 | | import "../../utils/Address.sol"; 10 | | import "../../utils/StorageSlot.sol"; 11 | | 12 | | /** 13 | | * @dev This abstract contract provides getters and event emitting update functions for 14 | | * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. 15 | | * 16 | | * _Available since v4.1._ 17 | | */ 18 | | abstract contract ERC1967Upgrade is IERC1967 { 19 | | // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 20 | | bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; 21 | | 22 | | /** 23 | | * @dev Storage slot with the address of the current implementation. 24 | | * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is 25 | | * validated in the constructor. 26 | | */ 27 | * | bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 28 | | 29 | | /** 30 | | * @dev Returns the current implementation address. 31 | | */ 32 | * | function _getImplementation() internal view returns (address) { 33 | * | return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; 34 | | } 35 | | 36 | | /** 37 | | * @dev Stores a new address in the EIP1967 implementation slot. 38 | | */ 39 | | function _setImplementation(address newImplementation) private { 40 | | require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); 41 | | StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; 42 | | } 43 | | 44 | | /** 45 | | * @dev Perform implementation upgrade 46 | | * 47 | | * Emits an {Upgraded} event. 48 | | */ 49 | | function _upgradeTo(address newImplementation) internal { 50 | | _setImplementation(newImplementation); 51 | | emit Upgraded(newImplementation); 52 | | } 53 | | 54 | | /** 55 | | * @dev Perform implementation upgrade with additional setup call. 56 | | * 57 | | * Emits an {Upgraded} event. 58 | | */ 59 | | function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { 60 | | _upgradeTo(newImplementation); 61 | | if (data.length > 0 || forceCall) { 62 | | Address.functionDelegateCall(newImplementation, data); 63 | | } 64 | | } 65 | | 66 | | /** 67 | | * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. 68 | | * 69 | | * Emits an {Upgraded} event. 70 | | */ 71 | | function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { 72 | | // Upgrades from old implementations will perform a rollback test. This test requires the new 73 | | // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing 74 | | // this special case will break upgrade paths from old UUPS implementation to new ones. 75 | | if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { 76 | | _setImplementation(newImplementation); 77 | | } else { 78 | | try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { 79 | | require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); 80 | | } catch { 81 | | revert("ERC1967Upgrade: new implementation is not UUPS"); 82 | | } 83 | | _upgradeToAndCall(newImplementation, data, forceCall); 84 | | } 85 | | } 86 | | 87 | | /** 88 | | * @dev Storage slot with the admin of the contract. 89 | | * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is 90 | | * validated in the constructor. 91 | | */ 92 | * | bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 93 | | 94 | | /** 95 | | * @dev Returns the current admin. 96 | | */ 97 | * | function _getAdmin() internal view returns (address) { 98 | * | return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; 99 | | } 100 | | 101 | | /** 102 | | * @dev Stores a new address in the EIP1967 admin slot. 103 | | */ 104 | | function _setAdmin(address newAdmin) private { 105 | | require(newAdmin != address(0), "ERC1967: new admin is the zero address"); 106 | | StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; 107 | | } 108 | | 109 | | /** 110 | | * @dev Changes the admin of the proxy. 111 | | * 112 | | * Emits an {AdminChanged} event. 113 | | */ 114 | | function _changeAdmin(address newAdmin) internal { 115 | | emit AdminChanged(_getAdmin(), newAdmin); 116 | | _setAdmin(newAdmin); 117 | | } 118 | | 119 | | /** 120 | | * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. 121 | | * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. 122 | | */ 123 | | bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; 124 | | 125 | | /** 126 | | * @dev Returns the current beacon. 127 | | */ 128 | | function _getBeacon() internal view returns (address) { 129 | | return StorageSlot.getAddressSlot(_BEACON_SLOT).value; 130 | | } 131 | | 132 | | /** 133 | | * @dev Stores a new beacon in the EIP1967 beacon slot. 134 | | */ 135 | | function _setBeacon(address newBeacon) private { 136 | | require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); 137 | | require( 138 | | Address.isContract(IBeacon(newBeacon).implementation()), 139 | | "ERC1967: beacon implementation is not a contract" 140 | | ); 141 | | StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; 142 | | } 143 | | 144 | | /** 145 | | * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does 146 | | * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). 147 | | * 148 | | * Emits a {BeaconUpgraded} event. 149 | | */ 150 | | function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { 151 | | _setBeacon(newBeacon); 152 | | emit BeaconUpgraded(newBeacon); 153 | | if (data.length > 0 || forceCall) { 154 | | Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); 155 | | } 156 | | } 157 | | } 158 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/Proxy.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM 8 | | * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to 9 | | * be specified by overriding the virtual {_implementation} function. 10 | | * 11 | | * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a 12 | | * different contract through the {_delegate} function. 13 | | * 14 | | * The success and return data of the delegated call will be returned back to the caller of the proxy. 15 | | */ 16 | | abstract contract Proxy { 17 | | /** 18 | | * @dev Delegates the current call to `implementation`. 19 | | * 20 | | * This function does not return to its internal call site, it will return directly to the external caller. 21 | | */ 22 | * | function _delegate(address implementation) internal virtual { 23 | | assembly { 24 | | // Copy msg.data. We take full control of memory in this inline assembly 25 | | // block because it will not return to Solidity code. We overwrite the 26 | | // Solidity scratch pad at memory position 0. 27 | * | calldatacopy(0, 0, calldatasize()) 28 | | 29 | | // Call the implementation. 30 | | // out and outsize are 0 because we don't know the size yet. 31 | * | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) 32 | | 33 | | // Copy the returned data. 34 | * | returndatacopy(0, 0, returndatasize()) 35 | | 36 | * | switch result 37 | | // delegatecall returns 0 on error. 38 | * | case 0 { 39 | * | revert(0, returndatasize()) 40 | | } 41 | | default { 42 | * | return(0, returndatasize()) 43 | | } 44 | | } 45 | | } 46 | | 47 | | /** 48 | | * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function 49 | | * and {_fallback} should delegate. 50 | | */ 51 | | function _implementation() internal view virtual returns (address); 52 | | 53 | | /** 54 | | * @dev Delegates the current call to the address returned by `_implementation()`. 55 | | * 56 | | * This function does not return to its internal call site, it will return directly to the external caller. 57 | | */ 58 | * | function _fallback() internal virtual { 59 | * | _beforeFallback(); 60 | * | _delegate(_implementation()); 61 | | } 62 | | 63 | | /** 64 | | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other 65 | | * function in the contract matches the call data. 66 | | */ 67 | | fallback() external payable virtual { 68 | * | _fallback(); 69 | | } 70 | | 71 | | /** 72 | | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data 73 | | * is empty. 74 | | */ 75 | | receive() external payable virtual { 76 | * | _fallback(); 77 | | } 78 | | 79 | | /** 80 | | * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` 81 | | * call, or as part of the Solidity `fallback` or `receive` functions. 82 | | * 83 | | * If overridden should call `super._beforeFallback()`. 84 | | */ 85 | * | function _beforeFallback() internal virtual {} 86 | | } 87 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev This is the interface that {BeaconProxy} expects of its beacon. 8 | | */ 9 | | interface IBeacon { 10 | | /** 11 | | * @dev Must return an address that can be used as a delegate call target. 12 | | * 13 | | * {BeaconProxy} will check that this address is a contract. 14 | | */ 15 | | function implementation() external view returns (address); 16 | | } 17 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./TransparentUpgradeableProxy.sol"; 7 | | import "../../access/Ownable.sol"; 8 | | 9 | | /** 10 | | * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an 11 | | * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. 12 | | */ 13 | * | contract ProxyAdmin is Ownable { 14 | | /** 15 | | * @dev Returns the current implementation of `proxy`. 16 | | * 17 | | * Requirements: 18 | | * 19 | | * - This contract must be the admin of `proxy`. 20 | | */ 21 | | function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) { 22 | | // We need to manually run the static call since the getter cannot be flagged as view 23 | | // bytes4(keccak256("implementation()")) == 0x5c60da1b 24 | | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); 25 | | require(success); 26 | | return abi.decode(returndata, (address)); 27 | | } 28 | | 29 | | /** 30 | | * @dev Returns the current admin of `proxy`. 31 | | * 32 | | * Requirements: 33 | | * 34 | | * - This contract must be the admin of `proxy`. 35 | | */ 36 | | function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) { 37 | | // We need to manually run the static call since the getter cannot be flagged as view 38 | | // bytes4(keccak256("admin()")) == 0xf851a440 39 | | (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); 40 | | require(success); 41 | | return abi.decode(returndata, (address)); 42 | | } 43 | | 44 | | /** 45 | | * @dev Changes the admin of `proxy` to `newAdmin`. 46 | | * 47 | | * Requirements: 48 | | * 49 | | * - This contract must be the current admin of `proxy`. 50 | | */ 51 | | function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { 52 | | proxy.changeAdmin(newAdmin); 53 | | } 54 | | 55 | | /** 56 | | * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. 57 | | * 58 | | * Requirements: 59 | | * 60 | | * - This contract must be the admin of `proxy`. 61 | | */ 62 | | function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { 63 | | proxy.upgradeTo(implementation); 64 | | } 65 | | 66 | | /** 67 | | * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See 68 | | * {TransparentUpgradeableProxy-upgradeToAndCall}. 69 | | * 70 | | * Requirements: 71 | | * 72 | | * - This contract must be the admin of `proxy`. 73 | | */ 74 | | function upgradeAndCall( 75 | | ITransparentUpgradeableProxy proxy, 76 | | address implementation, 77 | | bytes memory data 78 | | ) public payable virtual onlyOwner { 79 | | proxy.upgradeToAndCall{value: msg.value}(implementation, data); 80 | | } 81 | | } 82 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../ERC1967/ERC1967Proxy.sol"; 7 | | 8 | | /** 9 | | * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} 10 | | * does not implement this interface directly, and some of its functions are implemented by an internal dispatch 11 | | * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not 12 | | * include them in the ABI so this interface must be used to interact with it. 13 | | */ 14 | | interface ITransparentUpgradeableProxy is IERC1967 { 15 | | function admin() external view returns (address); 16 | | 17 | | function implementation() external view returns (address); 18 | | 19 | | function changeAdmin(address) external; 20 | | 21 | | function upgradeTo(address) external; 22 | | 23 | | function upgradeToAndCall(address, bytes memory) external payable; 24 | | } 25 | | 26 | | /** 27 | | * @dev This contract implements a proxy that is upgradeable by an admin. 28 | | * 29 | | * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector 30 | | * clashing], which can potentially be used in an attack, this contract uses the 31 | | * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two 32 | | * things that go hand in hand: 33 | | * 34 | | * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if 35 | | * that call matches one of the admin functions exposed by the proxy itself. 36 | | * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the 37 | | * implementation. If the admin tries to call a function on the implementation it will fail with an error that says 38 | | * "admin cannot fallback to proxy target". 39 | | * 40 | | * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing 41 | | * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due 42 | | * to sudden errors when trying to call a function from the proxy implementation. 43 | | * 44 | | * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, 45 | | * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. 46 | | * 47 | | * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not 48 | | * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch 49 | | * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to 50 | | * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the 51 | | * implementation. 52 | | * 53 | | * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler 54 | | * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function 55 | | * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could 56 | | * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised. 57 | | */ 58 | * | contract TransparentUpgradeableProxy is ERC1967Proxy { 59 | | /** 60 | | * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and 61 | | * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. 62 | | */ 63 | | constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) { 64 | | _changeAdmin(admin_); 65 | | } 66 | | 67 | | /** 68 | | * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. 69 | | * 70 | | * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the 71 | | * implementation provides a function with the same selector. 72 | | */ 73 | | modifier ifAdmin() { 74 | | if (msg.sender == _getAdmin()) { 75 | | _; 76 | | } else { 77 | | _fallback(); 78 | | } 79 | | } 80 | | 81 | | /** 82 | | * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior 83 | | */ 84 | * | function _fallback() internal virtual override { 85 | * | if (msg.sender == _getAdmin()) { 86 | | bytes memory ret; 87 | | bytes4 selector = msg.sig; 88 | | if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) { 89 | | ret = _dispatchUpgradeTo(); 90 | | } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) { 91 | | ret = _dispatchUpgradeToAndCall(); 92 | | } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) { 93 | | ret = _dispatchChangeAdmin(); 94 | | } else if (selector == ITransparentUpgradeableProxy.admin.selector) { 95 | | ret = _dispatchAdmin(); 96 | | } else if (selector == ITransparentUpgradeableProxy.implementation.selector) { 97 | | ret = _dispatchImplementation(); 98 | | } else { 99 | | revert("TransparentUpgradeableProxy: admin cannot fallback to proxy target"); 100 | | } 101 | | assembly { 102 | | return(add(ret, 0x20), mload(ret)) 103 | | } 104 | | } else { 105 | * | super._fallback(); 106 | | } 107 | | } 108 | | 109 | | /** 110 | | * @dev Returns the current admin. 111 | | * 112 | | * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the 113 | | * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. 114 | | * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` 115 | | */ 116 | | function _dispatchAdmin() private returns (bytes memory) { 117 | | _requireZeroValue(); 118 | | 119 | | address admin = _getAdmin(); 120 | | return abi.encode(admin); 121 | | } 122 | | 123 | | /** 124 | | * @dev Returns the current implementation. 125 | | * 126 | | * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the 127 | | * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. 128 | | * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` 129 | | */ 130 | | function _dispatchImplementation() private returns (bytes memory) { 131 | | _requireZeroValue(); 132 | | 133 | | address implementation = _implementation(); 134 | | return abi.encode(implementation); 135 | | } 136 | | 137 | | /** 138 | | * @dev Changes the admin of the proxy. 139 | | * 140 | | * Emits an {AdminChanged} event. 141 | | */ 142 | | function _dispatchChangeAdmin() private returns (bytes memory) { 143 | | _requireZeroValue(); 144 | | 145 | | address newAdmin = abi.decode(msg.data[4:], (address)); 146 | | _changeAdmin(newAdmin); 147 | | 148 | | return ""; 149 | | } 150 | | 151 | | /** 152 | | * @dev Upgrade the implementation of the proxy. 153 | | */ 154 | | function _dispatchUpgradeTo() private returns (bytes memory) { 155 | | _requireZeroValue(); 156 | | 157 | | address newImplementation = abi.decode(msg.data[4:], (address)); 158 | | _upgradeToAndCall(newImplementation, bytes(""), false); 159 | | 160 | | return ""; 161 | | } 162 | | 163 | | /** 164 | | * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified 165 | | * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the 166 | | * proxied contract. 167 | | */ 168 | | function _dispatchUpgradeToAndCall() private returns (bytes memory) { 169 | | (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); 170 | | _upgradeToAndCall(newImplementation, data, true); 171 | | 172 | | return ""; 173 | | } 174 | | 175 | | /** 176 | | * @dev Returns the current admin. 177 | | * 178 | | * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead. 179 | | */ 180 | | function _admin() internal view virtual returns (address) { 181 | | return _getAdmin(); 182 | | } 183 | | 184 | | /** 185 | | * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to 186 | | * emulate some proxy functions being non-payable while still allowing value to pass through. 187 | | */ 188 | | function _requireZeroValue() private { 189 | | require(msg.value == 0); 190 | | } 191 | | } 192 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/security/ReentrancyGuard.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Contract module that helps prevent reentrant calls to a function. 8 | | * 9 | | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 10 | | * available, which can be applied to functions to make sure there are no nested 11 | | * (reentrant) calls to them. 12 | | * 13 | | * Note that because there is a single `nonReentrant` guard, functions marked as 14 | | * `nonReentrant` may not call one another. This can be worked around by making 15 | | * those functions `private`, and then adding `external` `nonReentrant` entry 16 | | * points to them. 17 | | * 18 | | * TIP: If you would like to learn more about reentrancy and alternative ways 19 | | * to protect against it, check out our blog post 20 | | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. 21 | | */ 22 | | abstract contract ReentrancyGuard { 23 | | // Booleans are more expensive than uint256 or any type that takes up a full 24 | | // word because each write operation emits an extra SLOAD to first read the 25 | | // slot's contents, replace the bits taken up by the boolean, and then write 26 | | // back. This is the compiler's defense against contract upgrades and 27 | | // pointer aliasing, and it cannot be disabled. 28 | | 29 | | // The values being non-zero value makes deployment a bit more expensive, 30 | | // but in exchange the refund on every call to nonReentrant will be lower in 31 | | // amount. Since refunds are capped to a percentage of the total 32 | | // transaction's gas, it is best to keep them low in cases like this one, to 33 | | // increase the likelihood of the full refund coming into effect. 34 | * | uint256 private constant _NOT_ENTERED = 1; 35 | * | uint256 private constant _ENTERED = 2; 36 | | 37 | | uint256 private _status; 38 | | 39 | | constructor() { 40 | | _status = _NOT_ENTERED; 41 | | } 42 | | 43 | | /** 44 | | * @dev Prevents a contract from calling itself, directly or indirectly. 45 | | * Calling a `nonReentrant` function from another `nonReentrant` 46 | | * function is not supported. It is possible to prevent this from happening 47 | | * by making the `nonReentrant` function external, and making it call a 48 | | * `private` function that does the actual work. 49 | | */ 50 | | modifier nonReentrant() { 51 | * | _nonReentrantBefore(); 52 | | _; 53 | * | _nonReentrantAfter(); 54 | | } 55 | | 56 | * | function _nonReentrantBefore() private { 57 | | // On the first call to nonReentrant, _status will be _NOT_ENTERED 58 | * | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 59 | | 60 | | // Any calls to nonReentrant after this point will fail 61 | * | _status = _ENTERED; 62 | | } 63 | | 64 | * | function _nonReentrantAfter() private { 65 | | // By storing the original value once again, a refund is triggered (see 66 | | // https://eips.ethereum.org/EIPS/eip-2200) 67 | * | _status = _NOT_ENTERED; 68 | | } 69 | | 70 | | /** 71 | | * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a 72 | | * `nonReentrant` function in the call stack. 73 | | */ 74 | | function _reentrancyGuardEntered() internal view returns (bool) { 75 | | return _status == _ENTERED; 76 | | } 77 | | } 78 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../../utils/introspection/IERC165.sol"; 7 | | 8 | | /** 9 | | * @dev _Available since v3.1._ 10 | | */ 11 | | interface IERC1155Receiver is IERC165 { 12 | | /** 13 | | * @dev Handles the receipt of a single ERC1155 token type. This function is 14 | | * called at the end of a `safeTransferFrom` after the balance has been updated. 15 | | * 16 | | * NOTE: To accept the transfer, this must return 17 | | * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` 18 | | * (i.e. 0xf23a6e61, or its own function selector). 19 | | * 20 | | * @param operator The address which initiated the transfer (i.e. msg.sender) 21 | | * @param from The address which previously owned the token 22 | | * @param id The ID of the token being transferred 23 | | * @param value The amount of tokens being transferred 24 | | * @param data Additional data with no specified format 25 | | * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed 26 | | */ 27 | | function onERC1155Received( 28 | | address operator, 29 | | address from, 30 | | uint256 id, 31 | | uint256 value, 32 | | bytes calldata data 33 | | ) external returns (bytes4); 34 | | 35 | | /** 36 | | * @dev Handles the receipt of a multiple ERC1155 token types. This function 37 | | * is called at the end of a `safeBatchTransferFrom` after the balances have 38 | | * been updated. 39 | | * 40 | | * NOTE: To accept the transfer(s), this must return 41 | | * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` 42 | | * (i.e. 0xbc197c81, or its own function selector). 43 | | * 44 | | * @param operator The address which initiated the batch transfer (i.e. msg.sender) 45 | | * @param from The address which previously owned the token 46 | | * @param ids An array containing ids of each token being transferred (order and length must match values array) 47 | | * @param values An array containing amounts of each token being transferred (order and length must match ids array) 48 | | * @param data Additional data with no specified format 49 | | * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed 50 | | */ 51 | | function onERC1155BatchReceived( 52 | | address operator, 53 | | address from, 54 | | uint256[] calldata ids, 55 | | uint256[] calldata values, 56 | | bytes calldata data 57 | | ) external returns (bytes4); 58 | | } 59 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./IERC20.sol"; 7 | | import "./extensions/IERC20Metadata.sol"; 8 | | import "../../utils/Context.sol"; 9 | | 10 | | /** 11 | | * @dev Implementation of the {IERC20} interface. 12 | | * 13 | | * This implementation is agnostic to the way tokens are created. This means 14 | | * that a supply mechanism has to be added in a derived contract using {_mint}. 15 | | * For a generic mechanism see {ERC20PresetMinterPauser}. 16 | | * 17 | | * TIP: For a detailed writeup see our guide 18 | | * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How 19 | | * to implement supply mechanisms]. 20 | | * 21 | | * The default value of {decimals} is 18. To change this, you should override 22 | | * this function so it returns a different value. 23 | | * 24 | | * We have followed general OpenZeppelin Contracts guidelines: functions revert 25 | | * instead returning `false` on failure. This behavior is nonetheless 26 | | * conventional and does not conflict with the expectations of ERC20 27 | | * applications. 28 | | * 29 | | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 30 | | * This allows applications to reconstruct the allowance for all accounts just 31 | | * by listening to said events. Other implementations of the EIP may not emit 32 | | * these events, as it isn't required by the specification. 33 | | * 34 | | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 35 | | * functions have been added to mitigate the well-known issues around setting 36 | | * allowances. See {IERC20-approve}. 37 | | */ 38 | | contract ERC20 is Context, IERC20, IERC20Metadata { 39 | | mapping(address => uint256) private _balances; 40 | | 41 | | mapping(address => mapping(address => uint256)) private _allowances; 42 | | 43 | | uint256 private _totalSupply; 44 | | 45 | | string private _name; 46 | | string private _symbol; 47 | | 48 | | /** 49 | | * @dev Sets the values for {name} and {symbol}. 50 | | * 51 | | * All two of these values are immutable: they can only be set once during 52 | | * construction. 53 | | */ 54 | | constructor(string memory name_, string memory symbol_) { 55 | | _name = name_; 56 | | _symbol = symbol_; 57 | | } 58 | | 59 | | /** 60 | | * @dev Returns the name of the token. 61 | | */ 62 | | function name() public view virtual override returns (string memory) { 63 | | return _name; 64 | | } 65 | | 66 | | /** 67 | | * @dev Returns the symbol of the token, usually a shorter version of the 68 | | * name. 69 | | */ 70 | | function symbol() public view virtual override returns (string memory) { 71 | | return _symbol; 72 | | } 73 | | 74 | | /** 75 | | * @dev Returns the number of decimals used to get its user representation. 76 | | * For example, if `decimals` equals `2`, a balance of `505` tokens should 77 | | * be displayed to a user as `5.05` (`505 / 10 ** 2`). 78 | | * 79 | | * Tokens usually opt for a value of 18, imitating the relationship between 80 | | * Ether and Wei. This is the default value returned by this function, unless 81 | | * it's overridden. 82 | | * 83 | | * NOTE: This information is only used for _display_ purposes: it in 84 | | * no way affects any of the arithmetic of the contract, including 85 | | * {IERC20-balanceOf} and {IERC20-transfer}. 86 | | */ 87 | | function decimals() public view virtual override returns (uint8) { 88 | | return 18; 89 | | } 90 | | 91 | | /** 92 | | * @dev See {IERC20-totalSupply}. 93 | | */ 94 | * | function totalSupply() public view virtual override returns (uint256) { 95 | * | return _totalSupply; 96 | | } 97 | | 98 | | /** 99 | | * @dev See {IERC20-balanceOf}. 100 | | */ 101 | * | function balanceOf(address account) public view virtual override returns (uint256) { 102 | * | return _balances[account]; 103 | | } 104 | | 105 | | /** 106 | | * @dev See {IERC20-transfer}. 107 | | * 108 | | * Requirements: 109 | | * 110 | | * - `to` cannot be the zero address. 111 | | * - the caller must have a balance of at least `amount`. 112 | | */ 113 | * | function transfer(address to, uint256 amount) public virtual override returns (bool) { 114 | * | address owner = _msgSender(); 115 | * | _transfer(owner, to, amount); 116 | * | return true; 117 | | } 118 | | 119 | | /** 120 | | * @dev See {IERC20-allowance}. 121 | | */ 122 | * | function allowance(address owner, address spender) public view virtual override returns (uint256) { 123 | * | return _allowances[owner][spender]; 124 | | } 125 | | 126 | | /** 127 | | * @dev See {IERC20-approve}. 128 | | * 129 | | * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on 130 | | * `transferFrom`. This is semantically equivalent to an infinite approval. 131 | | * 132 | | * Requirements: 133 | | * 134 | | * - `spender` cannot be the zero address. 135 | | */ 136 | * | function approve(address spender, uint256 amount) public virtual override returns (bool) { 137 | * | address owner = _msgSender(); 138 | * | _approve(owner, spender, amount); 139 | * | return true; 140 | | } 141 | | 142 | | /** 143 | | * @dev See {IERC20-transferFrom}. 144 | | * 145 | | * Emits an {Approval} event indicating the updated allowance. This is not 146 | | * required by the EIP. See the note at the beginning of {ERC20}. 147 | | * 148 | | * NOTE: Does not update the allowance if the current allowance 149 | | * is the maximum `uint256`. 150 | | * 151 | | * Requirements: 152 | | * 153 | | * - `from` and `to` cannot be the zero address. 154 | | * - `from` must have a balance of at least `amount`. 155 | | * - the caller must have allowance for ``from``'s tokens of at least 156 | | * `amount`. 157 | | */ 158 | * | function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { 159 | * | address spender = _msgSender(); 160 | * | _spendAllowance(from, spender, amount); 161 | * | _transfer(from, to, amount); 162 | * | return true; 163 | | } 164 | | 165 | | /** 166 | | * @dev Atomically increases the allowance granted to `spender` by the caller. 167 | | * 168 | | * This is an alternative to {approve} that can be used as a mitigation for 169 | | * problems described in {IERC20-approve}. 170 | | * 171 | | * Emits an {Approval} event indicating the updated allowance. 172 | | * 173 | | * Requirements: 174 | | * 175 | | * - `spender` cannot be the zero address. 176 | | */ 177 | | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 178 | | address owner = _msgSender(); 179 | | _approve(owner, spender, allowance(owner, spender) + addedValue); 180 | | return true; 181 | | } 182 | | 183 | | /** 184 | | * @dev Atomically decreases the allowance granted to `spender` by the caller. 185 | | * 186 | | * This is an alternative to {approve} that can be used as a mitigation for 187 | | * problems described in {IERC20-approve}. 188 | | * 189 | | * Emits an {Approval} event indicating the updated allowance. 190 | | * 191 | | * Requirements: 192 | | * 193 | | * - `spender` cannot be the zero address. 194 | | * - `spender` must have allowance for the caller of at least 195 | | * `subtractedValue`. 196 | | */ 197 | | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 198 | | address owner = _msgSender(); 199 | | uint256 currentAllowance = allowance(owner, spender); 200 | | require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); 201 | | unchecked { 202 | | _approve(owner, spender, currentAllowance - subtractedValue); 203 | | } 204 | | 205 | | return true; 206 | | } 207 | | 208 | | /** 209 | | * @dev Moves `amount` of tokens from `from` to `to`. 210 | | * 211 | | * This internal function is equivalent to {transfer}, and can be used to 212 | | * e.g. implement automatic token fees, slashing mechanisms, etc. 213 | | * 214 | | * Emits a {Transfer} event. 215 | | * 216 | | * Requirements: 217 | | * 218 | | * - `from` cannot be the zero address. 219 | | * - `to` cannot be the zero address. 220 | | * - `from` must have a balance of at least `amount`. 221 | | */ 222 | * | function _transfer(address from, address to, uint256 amount) internal virtual { 223 | * | require(from != address(0), "ERC20: transfer from the zero address"); 224 | * | require(to != address(0), "ERC20: transfer to the zero address"); 225 | | 226 | * | _beforeTokenTransfer(from, to, amount); 227 | | 228 | * | uint256 fromBalance = _balances[from]; 229 | * | require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); 230 | | unchecked { 231 | * | _balances[from] = fromBalance - amount; 232 | | // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by 233 | | // decrementing then incrementing. 234 | * | _balances[to] += amount; 235 | | } 236 | | 237 | * | emit Transfer(from, to, amount); 238 | | 239 | * | _afterTokenTransfer(from, to, amount); 240 | | } 241 | | 242 | | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 243 | | * the total supply. 244 | | * 245 | | * Emits a {Transfer} event with `from` set to the zero address. 246 | | * 247 | | * Requirements: 248 | | * 249 | | * - `account` cannot be the zero address. 250 | | */ 251 | * | function _mint(address account, uint256 amount) internal virtual { 252 | * | require(account != address(0), "ERC20: mint to the zero address"); 253 | | 254 | * | _beforeTokenTransfer(address(0), account, amount); 255 | | 256 | * | _totalSupply += amount; 257 | | unchecked { 258 | | // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. 259 | * | _balances[account] += amount; 260 | | } 261 | * | emit Transfer(address(0), account, amount); 262 | | 263 | * | _afterTokenTransfer(address(0), account, amount); 264 | | } 265 | | 266 | | /** 267 | | * @dev Destroys `amount` tokens from `account`, reducing the 268 | | * total supply. 269 | | * 270 | | * Emits a {Transfer} event with `to` set to the zero address. 271 | | * 272 | | * Requirements: 273 | | * 274 | | * - `account` cannot be the zero address. 275 | | * - `account` must have at least `amount` tokens. 276 | | */ 277 | * | function _burn(address account, uint256 amount) internal virtual { 278 | * | require(account != address(0), "ERC20: burn from the zero address"); 279 | | 280 | * | _beforeTokenTransfer(account, address(0), amount); 281 | | 282 | * | uint256 accountBalance = _balances[account]; 283 | * | require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); 284 | | unchecked { 285 | * | _balances[account] = accountBalance - amount; 286 | | // Overflow not possible: amount <= accountBalance <= totalSupply. 287 | * | _totalSupply -= amount; 288 | | } 289 | | 290 | * | emit Transfer(account, address(0), amount); 291 | | 292 | * | _afterTokenTransfer(account, address(0), amount); 293 | | } 294 | | 295 | | /** 296 | | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 297 | | * 298 | | * This internal function is equivalent to `approve`, and can be used to 299 | | * e.g. set automatic allowances for certain subsystems, etc. 300 | | * 301 | | * Emits an {Approval} event. 302 | | * 303 | | * Requirements: 304 | | * 305 | | * - `owner` cannot be the zero address. 306 | | * - `spender` cannot be the zero address. 307 | | */ 308 | * | function _approve(address owner, address spender, uint256 amount) internal virtual { 309 | * | require(owner != address(0), "ERC20: approve from the zero address"); 310 | * | require(spender != address(0), "ERC20: approve to the zero address"); 311 | | 312 | * | _allowances[owner][spender] = amount; 313 | * | emit Approval(owner, spender, amount); 314 | | } 315 | | 316 | | /** 317 | | * @dev Updates `owner` s allowance for `spender` based on spent `amount`. 318 | | * 319 | | * Does not update the allowance amount in case of infinite allowance. 320 | | * Revert if not enough allowance is available. 321 | | * 322 | | * Might emit an {Approval} event. 323 | | */ 324 | * | function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { 325 | * | uint256 currentAllowance = allowance(owner, spender); 326 | * | if (currentAllowance != type(uint256).max) { 327 | * | require(currentAllowance >= amount, "ERC20: insufficient allowance"); 328 | | unchecked { 329 | * | _approve(owner, spender, currentAllowance - amount); 330 | | } 331 | | } 332 | | } 333 | | 334 | | /** 335 | | * @dev Hook that is called before any transfer of tokens. This includes 336 | | * minting and burning. 337 | | * 338 | | * Calling conditions: 339 | | * 340 | | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 341 | | * will be transferred to `to`. 342 | | * - when `from` is zero, `amount` tokens will be minted for `to`. 343 | | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 344 | | * - `from` and `to` are never both zero. 345 | | * 346 | | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 347 | | */ 348 | * | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} 349 | | 350 | | /** 351 | | * @dev Hook that is called after any transfer of tokens. This includes 352 | | * minting and burning. 353 | | * 354 | | * Calling conditions: 355 | | * 356 | | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 357 | | * has been transferred to `to`. 358 | | * - when `from` is zero, `amount` tokens have been minted for `to`. 359 | | * - when `to` is zero, `amount` of ``from``'s tokens have been burned. 360 | | * - `from` and `to` are never both zero. 361 | | * 362 | | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 363 | | */ 364 | * | function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} 365 | | } 366 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Interface of the ERC20 standard as defined in the EIP. 8 | | */ 9 | | interface IERC20 { 10 | | /** 11 | | * @dev Emitted when `value` tokens are moved from one account (`from`) to 12 | | * another (`to`). 13 | | * 14 | | * Note that `value` may be zero. 15 | | */ 16 | | event Transfer(address indexed from, address indexed to, uint256 value); 17 | | 18 | | /** 19 | | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 20 | | * a call to {approve}. `value` is the new allowance. 21 | | */ 22 | | event Approval(address indexed owner, address indexed spender, uint256 value); 23 | | 24 | | /** 25 | | * @dev Returns the amount of tokens in existence. 26 | | */ 27 | | function totalSupply() external view returns (uint256); 28 | | 29 | | /** 30 | | * @dev Returns the amount of tokens owned by `account`. 31 | | */ 32 | | function balanceOf(address account) external view returns (uint256); 33 | | 34 | | /** 35 | | * @dev Moves `amount` tokens from the caller's account to `to`. 36 | | * 37 | | * Returns a boolean value indicating whether the operation succeeded. 38 | | * 39 | | * Emits a {Transfer} event. 40 | | */ 41 | | function transfer(address to, uint256 amount) external returns (bool); 42 | | 43 | | /** 44 | | * @dev Returns the remaining number of tokens that `spender` will be 45 | | * allowed to spend on behalf of `owner` through {transferFrom}. This is 46 | | * zero by default. 47 | | * 48 | | * This value changes when {approve} or {transferFrom} are called. 49 | | */ 50 | | function allowance(address owner, address spender) external view returns (uint256); 51 | | 52 | | /** 53 | | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 54 | | * 55 | | * Returns a boolean value indicating whether the operation succeeded. 56 | | * 57 | | * IMPORTANT: Beware that changing an allowance with this method brings the risk 58 | | * that someone may use both the old and the new allowance by unfortunate 59 | | * transaction ordering. One possible solution to mitigate this race 60 | | * condition is to first reduce the spender's allowance to 0 and set the 61 | | * desired value afterwards: 62 | | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 63 | | * 64 | | * Emits an {Approval} event. 65 | | */ 66 | | function approve(address spender, uint256 amount) external returns (bool); 67 | | 68 | | /** 69 | | * @dev Moves `amount` tokens from `from` to `to` using the 70 | | * allowance mechanism. `amount` is then deducted from the caller's 71 | | * allowance. 72 | | * 73 | | * Returns a boolean value indicating whether the operation succeeded. 74 | | * 75 | | * Emits a {Transfer} event. 76 | | */ 77 | | function transferFrom(address from, address to, uint256 amount) external returns (bool); 78 | | } 79 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Permit.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./IERC20Permit.sol"; 7 | | import "../ERC20.sol"; 8 | | import "../../../utils/cryptography/ECDSA.sol"; 9 | | import "../../../utils/cryptography/EIP712.sol"; 10 | | import "../../../utils/Counters.sol"; 11 | | 12 | | /** 13 | | * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in 14 | | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. 15 | | * 16 | | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by 17 | | * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't 18 | | * need to send a transaction, and thus is not required to hold Ether at all. 19 | | * 20 | | * _Available since v3.4._ 21 | | */ 22 | | abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { 23 | | using Counters for Counters.Counter; 24 | | 25 | | mapping(address => Counters.Counter) private _nonces; 26 | | 27 | | // solhint-disable-next-line var-name-mixedcase 28 | | bytes32 private constant _PERMIT_TYPEHASH = 29 | | keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 30 | | /** 31 | | * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. 32 | | * However, to ensure consistency with the upgradeable transpiler, we will continue 33 | | * to reserve a slot. 34 | | * @custom:oz-renamed-from _PERMIT_TYPEHASH 35 | | */ 36 | | // solhint-disable-next-line var-name-mixedcase 37 | | bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; 38 | | 39 | | /** 40 | | * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. 41 | | * 42 | | * It's a good idea to use the same `name` that is defined as the ERC20 token name. 43 | | */ 44 | | constructor(string memory name) EIP712(name, "1") {} 45 | | 46 | | /** 47 | | * @dev See {IERC20Permit-permit}. 48 | | */ 49 | | function permit( 50 | | address owner, 51 | | address spender, 52 | | uint256 value, 53 | | uint256 deadline, 54 | | uint8 v, 55 | | bytes32 r, 56 | | bytes32 s 57 | | ) public virtual override { 58 | | require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); 59 | | 60 | | bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); 61 | | 62 | | bytes32 hash = _hashTypedDataV4(structHash); 63 | | 64 | | address signer = ECDSA.recover(hash, v, r, s); 65 | | require(signer == owner, "ERC20Permit: invalid signature"); 66 | | 67 | | _approve(owner, spender, value); 68 | | } 69 | | 70 | | /** 71 | | * @dev See {IERC20Permit-nonces}. 72 | | */ 73 | | function nonces(address owner) public view virtual override returns (uint256) { 74 | | return _nonces[owner].current(); 75 | | } 76 | | 77 | | /** 78 | | * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. 79 | | */ 80 | | // solhint-disable-next-line func-name-mixedcase 81 | | function DOMAIN_SEPARATOR() external view override returns (bytes32) { 82 | | return _domainSeparatorV4(); 83 | | } 84 | | 85 | | /** 86 | | * @dev "Consume a nonce": return the current value and increment. 87 | | * 88 | | * _Available since v4.1._ 89 | | */ 90 | | function _useNonce(address owner) internal virtual returns (uint256 current) { 91 | | Counters.Counter storage nonce = _nonces[owner]; 92 | | current = nonce.current(); 93 | | nonce.increment(); 94 | | } 95 | | } 96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./ERC20Permit.sol"; 7 | | import "../../../interfaces/IERC5805.sol"; 8 | | import "../../../utils/math/Math.sol"; 9 | | import "../../../utils/math/SafeCast.sol"; 10 | | import "../../../utils/cryptography/ECDSA.sol"; 11 | | 12 | | /** 13 | | * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, 14 | | * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. 15 | | * 16 | | * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. 17 | | * 18 | | * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either 19 | | * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting 20 | | * power can be queried through the public accessors {getVotes} and {getPastVotes}. 21 | | * 22 | | * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it 23 | | * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. 24 | | * 25 | | * _Available since v4.2._ 26 | | */ 27 | | abstract contract ERC20Votes is ERC20Permit, IERC5805 { 28 | | struct Checkpoint { 29 | | uint32 fromBlock; 30 | | uint224 votes; 31 | | } 32 | | 33 | | bytes32 private constant _DELEGATION_TYPEHASH = 34 | | keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); 35 | | 36 | | mapping(address => address) private _delegates; 37 | | mapping(address => Checkpoint[]) private _checkpoints; 38 | | Checkpoint[] private _totalSupplyCheckpoints; 39 | | 40 | | /** 41 | | * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). 42 | | */ 43 | | function clock() public view virtual override returns (uint48) { 44 | | return SafeCast.toUint48(block.number); 45 | | } 46 | | 47 | | /** 48 | | * @dev Description of the clock 49 | | */ 50 | | // solhint-disable-next-line func-name-mixedcase 51 | | function CLOCK_MODE() public view virtual override returns (string memory) { 52 | | // Check that the clock was not modified 53 | | require(clock() == block.number, "ERC20Votes: broken clock mode"); 54 | | return "mode=blocknumber&from=default"; 55 | | } 56 | | 57 | | /** 58 | | * @dev Get the `pos`-th checkpoint for `account`. 59 | | */ 60 | | function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { 61 | | return _checkpoints[account][pos]; 62 | | } 63 | | 64 | | /** 65 | | * @dev Get number of checkpoints for `account`. 66 | | */ 67 | | function numCheckpoints(address account) public view virtual returns (uint32) { 68 | | return SafeCast.toUint32(_checkpoints[account].length); 69 | | } 70 | | 71 | | /** 72 | | * @dev Get the address `account` is currently delegating to. 73 | | */ 74 | | function delegates(address account) public view virtual override returns (address) { 75 | | return _delegates[account]; 76 | | } 77 | | 78 | | /** 79 | | * @dev Gets the current votes balance for `account` 80 | | */ 81 | | function getVotes(address account) public view virtual override returns (uint256) { 82 | | uint256 pos = _checkpoints[account].length; 83 | | unchecked { 84 | | return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; 85 | | } 86 | | } 87 | | 88 | | /** 89 | | * @dev Retrieve the number of votes for `account` at the end of `timepoint`. 90 | | * 91 | | * Requirements: 92 | | * 93 | | * - `timepoint` must be in the past 94 | | */ 95 | | function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) { 96 | | require(timepoint < clock(), "ERC20Votes: future lookup"); 97 | | return _checkpointsLookup(_checkpoints[account], timepoint); 98 | | } 99 | | 100 | | /** 101 | | * @dev Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances. 102 | | * It is NOT the sum of all the delegated votes! 103 | | * 104 | | * Requirements: 105 | | * 106 | | * - `timepoint` must be in the past 107 | | */ 108 | | function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) { 109 | | require(timepoint < clock(), "ERC20Votes: future lookup"); 110 | | return _checkpointsLookup(_totalSupplyCheckpoints, timepoint); 111 | | } 112 | | 113 | | /** 114 | | * @dev Lookup a value in a list of (sorted) checkpoints. 115 | | */ 116 | | function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 timepoint) private view returns (uint256) { 117 | | // We run a binary search to look for the last (most recent) checkpoint taken before (or at) `timepoint`. 118 | | // 119 | | // Initially we check if the block is recent to narrow the search range. 120 | | // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). 121 | | // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. 122 | | // - If the middle checkpoint is after `timepoint`, we look in [low, mid) 123 | | // - If the middle checkpoint is before or equal to `timepoint`, we look in [mid+1, high) 124 | | // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not 125 | | // out of bounds (in which case we're looking too far in the past and the result is 0). 126 | | // Note that if the latest checkpoint available is exactly for `timepoint`, we end up with an index that is 127 | | // past the end of the array, so we technically don't find a checkpoint after `timepoint`, but it works out 128 | | // the same. 129 | | uint256 length = ckpts.length; 130 | | 131 | | uint256 low = 0; 132 | | uint256 high = length; 133 | | 134 | | if (length > 5) { 135 | | uint256 mid = length - Math.sqrt(length); 136 | | if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) { 137 | | high = mid; 138 | | } else { 139 | | low = mid + 1; 140 | | } 141 | | } 142 | | 143 | | while (low < high) { 144 | | uint256 mid = Math.average(low, high); 145 | | if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) { 146 | | high = mid; 147 | | } else { 148 | | low = mid + 1; 149 | | } 150 | | } 151 | | 152 | | unchecked { 153 | | return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes; 154 | | } 155 | | } 156 | | 157 | | /** 158 | | * @dev Delegate votes from the sender to `delegatee`. 159 | | */ 160 | | function delegate(address delegatee) public virtual override { 161 | | _delegate(_msgSender(), delegatee); 162 | | } 163 | | 164 | | /** 165 | | * @dev Delegates votes from signer to `delegatee` 166 | | */ 167 | | function delegateBySig( 168 | | address delegatee, 169 | | uint256 nonce, 170 | | uint256 expiry, 171 | | uint8 v, 172 | | bytes32 r, 173 | | bytes32 s 174 | | ) public virtual override { 175 | | require(block.timestamp <= expiry, "ERC20Votes: signature expired"); 176 | | address signer = ECDSA.recover( 177 | | _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), 178 | | v, 179 | | r, 180 | | s 181 | | ); 182 | | require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); 183 | | _delegate(signer, delegatee); 184 | | } 185 | | 186 | | /** 187 | | * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). 188 | | */ 189 | | function _maxSupply() internal view virtual returns (uint224) { 190 | | return type(uint224).max; 191 | | } 192 | | 193 | | /** 194 | | * @dev Snapshots the totalSupply after it has been increased. 195 | | */ 196 | | function _mint(address account, uint256 amount) internal virtual override { 197 | | super._mint(account, amount); 198 | | require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); 199 | | 200 | | _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); 201 | | } 202 | | 203 | | /** 204 | | * @dev Snapshots the totalSupply after it has been decreased. 205 | | */ 206 | | function _burn(address account, uint256 amount) internal virtual override { 207 | | super._burn(account, amount); 208 | | 209 | | _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); 210 | | } 211 | | 212 | | /** 213 | | * @dev Move voting power when tokens are transferred. 214 | | * 215 | | * Emits a {IVotes-DelegateVotesChanged} event. 216 | | */ 217 | | function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual override { 218 | | super._afterTokenTransfer(from, to, amount); 219 | | 220 | | _moveVotingPower(delegates(from), delegates(to), amount); 221 | | } 222 | | 223 | | /** 224 | | * @dev Change delegation for `delegator` to `delegatee`. 225 | | * 226 | | * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}. 227 | | */ 228 | | function _delegate(address delegator, address delegatee) internal virtual { 229 | | address currentDelegate = delegates(delegator); 230 | | uint256 delegatorBalance = balanceOf(delegator); 231 | | _delegates[delegator] = delegatee; 232 | | 233 | | emit DelegateChanged(delegator, currentDelegate, delegatee); 234 | | 235 | | _moveVotingPower(currentDelegate, delegatee, delegatorBalance); 236 | | } 237 | | 238 | | function _moveVotingPower(address src, address dst, uint256 amount) private { 239 | | if (src != dst && amount > 0) { 240 | | if (src != address(0)) { 241 | | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); 242 | | emit DelegateVotesChanged(src, oldWeight, newWeight); 243 | | } 244 | | 245 | | if (dst != address(0)) { 246 | | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); 247 | | emit DelegateVotesChanged(dst, oldWeight, newWeight); 248 | | } 249 | | } 250 | | } 251 | | 252 | | function _writeCheckpoint( 253 | | Checkpoint[] storage ckpts, 254 | | function(uint256, uint256) view returns (uint256) op, 255 | | uint256 delta 256 | | ) private returns (uint256 oldWeight, uint256 newWeight) { 257 | | uint256 pos = ckpts.length; 258 | | 259 | | unchecked { 260 | | Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1); 261 | | 262 | | oldWeight = oldCkpt.votes; 263 | | newWeight = op(oldWeight, delta); 264 | | 265 | | if (pos > 0 && oldCkpt.fromBlock == clock()) { 266 | | _unsafeAccess(ckpts, pos - 1).votes = SafeCast.toUint224(newWeight); 267 | | } else { 268 | | ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(clock()), votes: SafeCast.toUint224(newWeight)})); 269 | | } 270 | | } 271 | | } 272 | | 273 | | function _add(uint256 a, uint256 b) private pure returns (uint256) { 274 | | return a + b; 275 | | } 276 | | 277 | | function _subtract(uint256 a, uint256 b) private pure returns (uint256) { 278 | | return a - b; 279 | | } 280 | | 281 | | /** 282 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. 283 | | */ 284 | | function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) { 285 | | assembly { 286 | | mstore(0, ckpts.slot) 287 | | result.slot := add(keccak256(0, 0x20), pos) 288 | | } 289 | | } 290 | | } 291 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../IERC20.sol"; 7 | | 8 | | /** 9 | | * @dev Interface for the optional metadata functions from the ERC20 standard. 10 | | * 11 | | * _Available since v4.1._ 12 | | */ 13 | | interface IERC20Metadata is IERC20 { 14 | | /** 15 | | * @dev Returns the name of the token. 16 | | */ 17 | | function name() external view returns (string memory); 18 | | 19 | | /** 20 | | * @dev Returns the symbol of the token. 21 | | */ 22 | | function symbol() external view returns (string memory); 23 | | 24 | | /** 25 | | * @dev Returns the decimals places of the token. 26 | | */ 27 | | function decimals() external view returns (uint8); 28 | | } 29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in 8 | | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. 9 | | * 10 | | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by 11 | | * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't 12 | | * need to send a transaction, and thus is not required to hold Ether at all. 13 | | */ 14 | | interface IERC20Permit { 15 | | /** 16 | | * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, 17 | | * given ``owner``'s signed approval. 18 | | * 19 | | * IMPORTANT: The same issues {IERC20-approve} has related to transaction 20 | | * ordering also apply here. 21 | | * 22 | | * Emits an {Approval} event. 23 | | * 24 | | * Requirements: 25 | | * 26 | | * - `spender` cannot be the zero address. 27 | | * - `deadline` must be a timestamp in the future. 28 | | * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` 29 | | * over the EIP712-formatted function arguments. 30 | | * - the signature must use ``owner``'s current nonce (see {nonces}). 31 | | * 32 | | * For more information on the signature format, see the 33 | | * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP 34 | | * section]. 35 | | */ 36 | | function permit( 37 | | address owner, 38 | | address spender, 39 | | uint256 value, 40 | | uint256 deadline, 41 | | uint8 v, 42 | | bytes32 r, 43 | | bytes32 s 44 | | ) external; 45 | | 46 | | /** 47 | | * @dev Returns the current nonce for `owner`. This value must be 48 | | * included whenever a signature is generated for {permit}. 49 | | * 50 | | * Every successful call to {permit} increases ``owner``'s nonce by one. This 51 | | * prevents a signature from being used multiple times. 52 | | */ 53 | | function nonces(address owner) external view returns (uint256); 54 | | 55 | | /** 56 | | * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. 57 | | */ 58 | | // solhint-disable-next-line func-name-mixedcase 59 | | function DOMAIN_SEPARATOR() external view returns (bytes32); 60 | | } 61 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../IERC20.sol"; 7 | | import "../extensions/IERC20Permit.sol"; 8 | | import "../../../utils/Address.sol"; 9 | | 10 | | /** 11 | | * @title SafeERC20 12 | | * @dev Wrappers around ERC20 operations that throw on failure (when the token 13 | | * contract returns false). Tokens that return no value (and instead revert or 14 | | * throw on failure) are also supported, non-reverting calls are assumed to be 15 | | * successful. 16 | | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 17 | | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 18 | | */ 19 | * | library SafeERC20 { 20 | | using Address for address; 21 | | 22 | | /** 23 | | * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, 24 | | * non-reverting calls are assumed to be successful. 25 | | */ 26 | * | function safeTransfer(IERC20 token, address to, uint256 value) internal { 27 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 28 | | } 29 | | 30 | | /** 31 | | * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the 32 | | * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. 33 | | */ 34 | * | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 35 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 36 | | } 37 | | 38 | | /** 39 | | * @dev Deprecated. This function has issues similar to the ones found in 40 | | * {IERC20-approve}, and its usage is discouraged. 41 | | * 42 | | * Whenever possible, use {safeIncreaseAllowance} and 43 | | * {safeDecreaseAllowance} instead. 44 | | */ 45 | * | function safeApprove(IERC20 token, address spender, uint256 value) internal { 46 | | // safeApprove should only be called when setting an initial allowance, 47 | | // or when resetting it to zero. To increase and decrease it, use 48 | | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 49 | * | require( 50 | * | (value == 0) || (token.allowance(address(this), spender) == 0), 51 | | "SafeERC20: approve from non-zero to non-zero allowance" 52 | | ); 53 | * | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 54 | | } 55 | | 56 | | /** 57 | | * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, 58 | | * non-reverting calls are assumed to be successful. 59 | | */ 60 | | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 61 | | uint256 oldAllowance = token.allowance(address(this), spender); 62 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); 63 | | } 64 | | 65 | | /** 66 | | * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, 67 | | * non-reverting calls are assumed to be successful. 68 | | */ 69 | | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 70 | | unchecked { 71 | | uint256 oldAllowance = token.allowance(address(this), spender); 72 | | require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); 73 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); 74 | | } 75 | | } 76 | | 77 | | /** 78 | | * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, 79 | | * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval 80 | | * to be set to zero before setting it to a non-zero value, such as USDT. 81 | | */ 82 | | function forceApprove(IERC20 token, address spender, uint256 value) internal { 83 | | bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); 84 | | 85 | | if (!_callOptionalReturnBool(token, approvalCall)) { 86 | | _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); 87 | | _callOptionalReturn(token, approvalCall); 88 | | } 89 | | } 90 | | 91 | | /** 92 | | * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. 93 | | * Revert on invalid signature. 94 | | */ 95 | | function safePermit( 96 | | IERC20Permit token, 97 | | address owner, 98 | | address spender, 99 | | uint256 value, 100 | | uint256 deadline, 101 | | uint8 v, 102 | | bytes32 r, 103 | | bytes32 s 104 | | ) internal { 105 | | uint256 nonceBefore = token.nonces(owner); 106 | | token.permit(owner, spender, value, deadline, v, r, s); 107 | | uint256 nonceAfter = token.nonces(owner); 108 | | require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); 109 | | } 110 | | 111 | | /** 112 | | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 113 | | * on the return value: the return value is optional (but if data is returned, it must not be false). 114 | | * @param token The token targeted by the call. 115 | | * @param data The call data (encoded using abi.encode or one of its variants). 116 | | */ 117 | * | function _callOptionalReturn(IERC20 token, bytes memory data) private { 118 | | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 119 | | // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that 120 | | // the target address contains contract code and also asserts for success in the low-level call. 121 | | 122 | * | bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); 123 | * | require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 124 | | } 125 | | 126 | | /** 127 | | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 128 | | * on the return value: the return value is optional (but if data is returned, it must not be false). 129 | | * @param token The token targeted by the call. 130 | | * @param data The call data (encoded using abi.encode or one of its variants). 131 | | * 132 | | * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. 133 | | */ 134 | | function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { 135 | | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 136 | | // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false 137 | | // and not revert is the subcall reverts. 138 | | 139 | | (bool success, bytes memory returndata) = address(token).call(data); 140 | | return 141 | | success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); 142 | | } 143 | | } 144 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @title ERC721 token receiver interface 8 | | * @dev Interface for any contract that wants to support safeTransfers 9 | | * from ERC721 asset contracts. 10 | | */ 11 | | interface IERC721Receiver { 12 | | /** 13 | | * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} 14 | | * by `operator` from `from`, this function is called. 15 | | * 16 | | * It must return its Solidity selector to confirm the token transfer. 17 | | * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. 18 | | * 19 | | * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. 20 | | */ 21 | | function onERC721Received( 22 | | address operator, 23 | | address from, 24 | | uint256 tokenId, 25 | | bytes calldata data 26 | | ) external returns (bytes4); 27 | | } 28 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Address.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) 3 | | 4 | | pragma solidity ^0.8.1; 5 | | 6 | | /** 7 | | * @dev Collection of functions related to the address type 8 | | */ 9 | * | library Address { 10 | | /** 11 | | * @dev Returns true if `account` is a contract. 12 | | * 13 | | * [IMPORTANT] 14 | | * ==== 15 | | * It is unsafe to assume that an address for which this function returns 16 | | * false is an externally-owned account (EOA) and not a contract. 17 | | * 18 | | * Among others, `isContract` will return false for the following 19 | | * types of addresses: 20 | | * 21 | | * - an externally-owned account 22 | | * - a contract in construction 23 | | * - an address where a contract will be created 24 | | * - an address where a contract lived, but was destroyed 25 | | * 26 | | * Furthermore, `isContract` will also return true if the target contract within 27 | | * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, 28 | | * which only has an effect at the end of a transaction. 29 | | * ==== 30 | | * 31 | | * [IMPORTANT] 32 | | * ==== 33 | | * You shouldn't rely on `isContract` to protect against flash loan attacks! 34 | | * 35 | | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets 36 | | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract 37 | | * constructor. 38 | | * ==== 39 | | */ 40 | * | function isContract(address account) internal view returns (bool) { 41 | | // This method relies on extcodesize/address.code.length, which returns 0 42 | | // for contracts in construction, since the code is only stored at the end 43 | | // of the constructor execution. 44 | | 45 | * | return account.code.length > 0; 46 | | } 47 | | 48 | | /** 49 | | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 50 | | * `recipient`, forwarding all available gas and reverting on errors. 51 | | * 52 | | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 53 | | * of certain opcodes, possibly making contracts go over the 2300 gas limit 54 | | * imposed by `transfer`, making them unable to receive funds via 55 | | * `transfer`. {sendValue} removes this limitation. 56 | | * 57 | | * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 58 | | * 59 | | * IMPORTANT: because control is transferred to `recipient`, care must be 60 | | * taken to not create reentrancy vulnerabilities. Consider using 61 | | * {ReentrancyGuard} or the 62 | | * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 63 | | */ 64 | | function sendValue(address payable recipient, uint256 amount) internal { 65 | | require(address(this).balance >= amount, "Address: insufficient balance"); 66 | | 67 | | (bool success, ) = recipient.call{value: amount}(""); 68 | | require(success, "Address: unable to send value, recipient may have reverted"); 69 | | } 70 | | 71 | | /** 72 | | * @dev Performs a Solidity function call using a low level `call`. A 73 | | * plain `call` is an unsafe replacement for a function call: use this 74 | | * function instead. 75 | | * 76 | | * If `target` reverts with a revert reason, it is bubbled up by this 77 | | * function (like regular Solidity function calls). 78 | | * 79 | | * Returns the raw returned data. To convert to the expected return value, 80 | | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 81 | | * 82 | | * Requirements: 83 | | * 84 | | * - `target` must be a contract. 85 | | * - calling `target` with `data` must not revert. 86 | | * 87 | | * _Available since v3.1._ 88 | | */ 89 | | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 90 | | return functionCallWithValue(target, data, 0, "Address: low-level call failed"); 91 | | } 92 | | 93 | | /** 94 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 95 | | * `errorMessage` as a fallback revert reason when `target` reverts. 96 | | * 97 | | * _Available since v3.1._ 98 | | */ 99 | * | function functionCall( 100 | | address target, 101 | | bytes memory data, 102 | | string memory errorMessage 103 | * | ) internal returns (bytes memory) { 104 | * | return functionCallWithValue(target, data, 0, errorMessage); 105 | | } 106 | | 107 | | /** 108 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 109 | | * but also transferring `value` wei to `target`. 110 | | * 111 | | * Requirements: 112 | | * 113 | | * - the calling contract must have an ETH balance of at least `value`. 114 | | * - the called Solidity function must be `payable`. 115 | | * 116 | | * _Available since v3.1._ 117 | | */ 118 | | function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 119 | | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 120 | | } 121 | | 122 | | /** 123 | | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 124 | | * with `errorMessage` as a fallback revert reason when `target` reverts. 125 | | * 126 | | * _Available since v3.1._ 127 | | */ 128 | * | function functionCallWithValue( 129 | | address target, 130 | | bytes memory data, 131 | | uint256 value, 132 | | string memory errorMessage 133 | * | ) internal returns (bytes memory) { 134 | * | require(address(this).balance >= value, "Address: insufficient balance for call"); 135 | * | (bool success, bytes memory returndata) = target.call{value: value}(data); 136 | * | return verifyCallResultFromTarget(target, success, returndata, errorMessage); 137 | | } 138 | | 139 | | /** 140 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 141 | | * but performing a static call. 142 | | * 143 | | * _Available since v3.3._ 144 | | */ 145 | | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 146 | | return functionStaticCall(target, data, "Address: low-level static call failed"); 147 | | } 148 | | 149 | | /** 150 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 151 | | * but performing a static call. 152 | | * 153 | | * _Available since v3.3._ 154 | | */ 155 | | function functionStaticCall( 156 | | address target, 157 | | bytes memory data, 158 | | string memory errorMessage 159 | | ) internal view returns (bytes memory) { 160 | | (bool success, bytes memory returndata) = target.staticcall(data); 161 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage); 162 | | } 163 | | 164 | | /** 165 | | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 166 | | * but performing a delegate call. 167 | | * 168 | | * _Available since v3.4._ 169 | | */ 170 | | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 171 | | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 172 | | } 173 | | 174 | | /** 175 | | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 176 | | * but performing a delegate call. 177 | | * 178 | | * _Available since v3.4._ 179 | | */ 180 | | function functionDelegateCall( 181 | | address target, 182 | | bytes memory data, 183 | | string memory errorMessage 184 | | ) internal returns (bytes memory) { 185 | | (bool success, bytes memory returndata) = target.delegatecall(data); 186 | | return verifyCallResultFromTarget(target, success, returndata, errorMessage); 187 | | } 188 | | 189 | | /** 190 | | * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling 191 | | * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. 192 | | * 193 | | * _Available since v4.8._ 194 | | */ 195 | * | function verifyCallResultFromTarget( 196 | | address target, 197 | | bool success, 198 | | bytes memory returndata, 199 | | string memory errorMessage 200 | * | ) internal view returns (bytes memory) { 201 | * | if (success) { 202 | * | if (returndata.length == 0) { 203 | | // only check isContract if the call was successful and the return data is empty 204 | | // otherwise we already know that it was a contract 205 | | require(isContract(target), "Address: call to non-contract"); 206 | | } 207 | * | return returndata; 208 | | } else { 209 | * | _revert(returndata, errorMessage); 210 | | } 211 | | } 212 | | 213 | | /** 214 | | * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the 215 | | * revert reason or using the provided one. 216 | | * 217 | | * _Available since v4.3._ 218 | | */ 219 | | function verifyCallResult( 220 | | bool success, 221 | | bytes memory returndata, 222 | | string memory errorMessage 223 | | ) internal pure returns (bytes memory) { 224 | | if (success) { 225 | | return returndata; 226 | | } else { 227 | | _revert(returndata, errorMessage); 228 | | } 229 | | } 230 | | 231 | * | function _revert(bytes memory returndata, string memory errorMessage) private pure { 232 | | // Look for revert reason and bubble it up if present 233 | * | if (returndata.length > 0) { 234 | | // The easiest way to bubble the revert reason is using memory via assembly 235 | | /// @solidity memory-safe-assembly 236 | | assembly { 237 | * | let returndata_size := mload(returndata) 238 | * | revert(add(32, returndata), returndata_size) 239 | | } 240 | | } else { 241 | | revert(errorMessage); 242 | | } 243 | | } 244 | | } 245 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Checkpoints.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Checkpoints.sol) 3 | | // This file was procedurally generated from scripts/generate/templates/Checkpoints.js. 4 | | 5 | | pragma solidity ^0.8.0; 6 | | 7 | | import "./math/Math.sol"; 8 | | import "./math/SafeCast.sol"; 9 | | 10 | | /** 11 | | * @dev This library defines the `History` struct, for checkpointing values as they change at different points in 12 | | * time, and later looking up past values by block number. See {Votes} as an example. 13 | | * 14 | | * To create a history of checkpoints define a variable type `Checkpoints.History` in your contract, and store a new 15 | | * checkpoint for the current transaction block using the {push} function. 16 | | * 17 | | * _Available since v4.5._ 18 | | */ 19 | * | library Checkpoints { 20 | | struct History { 21 | | Checkpoint[] _checkpoints; 22 | | } 23 | | 24 | | struct Checkpoint { 25 | | uint32 _blockNumber; 26 | | uint224 _value; 27 | | } 28 | | 29 | | /** 30 | | * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one 31 | | * before it is returned, or zero otherwise. Because the number returned corresponds to that at the end of the 32 | | * block, the requested block number must be in the past, excluding the current block. 33 | | */ 34 | | function getAtBlock(History storage self, uint256 blockNumber) internal view returns (uint256) { 35 | | require(blockNumber < block.number, "Checkpoints: block not yet mined"); 36 | | uint32 key = SafeCast.toUint32(blockNumber); 37 | | 38 | | uint256 len = self._checkpoints.length; 39 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); 40 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 41 | | } 42 | | 43 | | /** 44 | | * @dev Returns the value at a given block number. If a checkpoint is not available at that block, the closest one 45 | | * before it is returned, or zero otherwise. Similar to {upperLookup} but optimized for the case when the searched 46 | | * checkpoint is probably "recent", defined as being among the last sqrt(N) checkpoints where N is the number of 47 | | * checkpoints. 48 | | */ 49 | | function getAtProbablyRecentBlock(History storage self, uint256 blockNumber) internal view returns (uint256) { 50 | | require(blockNumber < block.number, "Checkpoints: block not yet mined"); 51 | | uint32 key = SafeCast.toUint32(blockNumber); 52 | | 53 | | uint256 len = self._checkpoints.length; 54 | | 55 | | uint256 low = 0; 56 | | uint256 high = len; 57 | | 58 | | if (len > 5) { 59 | | uint256 mid = len - Math.sqrt(len); 60 | | if (key < _unsafeAccess(self._checkpoints, mid)._blockNumber) { 61 | | high = mid; 62 | | } else { 63 | | low = mid + 1; 64 | | } 65 | | } 66 | | 67 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); 68 | | 69 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 70 | | } 71 | | 72 | | /** 73 | | * @dev Pushes a value onto a History so that it is stored as the checkpoint for the current block. 74 | | * 75 | | * Returns previous value and new value. 76 | | */ 77 | | function push(History storage self, uint256 value) internal returns (uint256, uint256) { 78 | | return _insert(self._checkpoints, SafeCast.toUint32(block.number), SafeCast.toUint224(value)); 79 | | } 80 | | 81 | | /** 82 | | * @dev Pushes a value onto a History, by updating the latest value using binary operation `op`. The new value will 83 | | * be set to `op(latest, delta)`. 84 | | * 85 | | * Returns previous value and new value. 86 | | */ 87 | | function push( 88 | | History storage self, 89 | | function(uint256, uint256) view returns (uint256) op, 90 | | uint256 delta 91 | | ) internal returns (uint256, uint256) { 92 | | return push(self, op(latest(self), delta)); 93 | | } 94 | | 95 | | /** 96 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. 97 | | */ 98 | | function latest(History storage self) internal view returns (uint224) { 99 | | uint256 pos = self._checkpoints.length; 100 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 101 | | } 102 | | 103 | | /** 104 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value 105 | | * in the most recent checkpoint. 106 | | */ 107 | | function latestCheckpoint( 108 | | History storage self 109 | | ) internal view returns (bool exists, uint32 _blockNumber, uint224 _value) { 110 | | uint256 pos = self._checkpoints.length; 111 | | if (pos == 0) { 112 | | return (false, 0, 0); 113 | | } else { 114 | | Checkpoint memory ckpt = _unsafeAccess(self._checkpoints, pos - 1); 115 | | return (true, ckpt._blockNumber, ckpt._value); 116 | | } 117 | | } 118 | | 119 | | /** 120 | | * @dev Returns the number of checkpoint. 121 | | */ 122 | | function length(History storage self) internal view returns (uint256) { 123 | | return self._checkpoints.length; 124 | | } 125 | | 126 | | /** 127 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, 128 | | * or by updating the last one. 129 | | */ 130 | | function _insert(Checkpoint[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) { 131 | | uint256 pos = self.length; 132 | | 133 | | if (pos > 0) { 134 | | // Copying to memory is important here. 135 | | Checkpoint memory last = _unsafeAccess(self, pos - 1); 136 | | 137 | | // Checkpoint keys must be non-decreasing. 138 | | require(last._blockNumber <= key, "Checkpoint: decreasing keys"); 139 | | 140 | | // Update or push new checkpoint 141 | | if (last._blockNumber == key) { 142 | | _unsafeAccess(self, pos - 1)._value = value; 143 | | } else { 144 | | self.push(Checkpoint({_blockNumber: key, _value: value})); 145 | | } 146 | | return (last._value, value); 147 | | } else { 148 | | self.push(Checkpoint({_blockNumber: key, _value: value})); 149 | | return (0, value); 150 | | } 151 | | } 152 | | 153 | | /** 154 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none. 155 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 156 | | * 157 | | * WARNING: `high` should not be greater than the array's length. 158 | | */ 159 | | function _upperBinaryLookup( 160 | | Checkpoint[] storage self, 161 | | uint32 key, 162 | | uint256 low, 163 | | uint256 high 164 | | ) private view returns (uint256) { 165 | | while (low < high) { 166 | | uint256 mid = Math.average(low, high); 167 | | if (_unsafeAccess(self, mid)._blockNumber > key) { 168 | | high = mid; 169 | | } else { 170 | | low = mid + 1; 171 | | } 172 | | } 173 | | return high; 174 | | } 175 | | 176 | | /** 177 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none. 178 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 179 | | * 180 | | * WARNING: `high` should not be greater than the array's length. 181 | | */ 182 | | function _lowerBinaryLookup( 183 | | Checkpoint[] storage self, 184 | | uint32 key, 185 | | uint256 low, 186 | | uint256 high 187 | | ) private view returns (uint256) { 188 | | while (low < high) { 189 | | uint256 mid = Math.average(low, high); 190 | | if (_unsafeAccess(self, mid)._blockNumber < key) { 191 | | low = mid + 1; 192 | | } else { 193 | | high = mid; 194 | | } 195 | | } 196 | | return high; 197 | | } 198 | | 199 | | /** 200 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. 201 | | */ 202 | | function _unsafeAccess(Checkpoint[] storage self, uint256 pos) private pure returns (Checkpoint storage result) { 203 | | assembly { 204 | | mstore(0, self.slot) 205 | | result.slot := add(keccak256(0, 0x20), pos) 206 | | } 207 | | } 208 | | 209 | | struct Trace224 { 210 | | Checkpoint224[] _checkpoints; 211 | | } 212 | | 213 | | struct Checkpoint224 { 214 | | uint32 _key; 215 | | uint224 _value; 216 | | } 217 | | 218 | | /** 219 | | * @dev Pushes a (`key`, `value`) pair into a Trace224 so that it is stored as the checkpoint. 220 | | * 221 | | * Returns previous value and new value. 222 | | */ 223 | | function push(Trace224 storage self, uint32 key, uint224 value) internal returns (uint224, uint224) { 224 | | return _insert(self._checkpoints, key, value); 225 | | } 226 | | 227 | | /** 228 | | * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none. 229 | | */ 230 | | function lowerLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { 231 | | uint256 len = self._checkpoints.length; 232 | | uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); 233 | | return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; 234 | | } 235 | | 236 | | /** 237 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none. 238 | | */ 239 | | function upperLookup(Trace224 storage self, uint32 key) internal view returns (uint224) { 240 | | uint256 len = self._checkpoints.length; 241 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); 242 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 243 | | } 244 | | 245 | | /** 246 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none. 247 | | * 248 | | * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys). 249 | | */ 250 | | function upperLookupRecent(Trace224 storage self, uint32 key) internal view returns (uint224) { 251 | | uint256 len = self._checkpoints.length; 252 | | 253 | | uint256 low = 0; 254 | | uint256 high = len; 255 | | 256 | | if (len > 5) { 257 | | uint256 mid = len - Math.sqrt(len); 258 | | if (key < _unsafeAccess(self._checkpoints, mid)._key) { 259 | | high = mid; 260 | | } else { 261 | | low = mid + 1; 262 | | } 263 | | } 264 | | 265 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); 266 | | 267 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 268 | | } 269 | | 270 | | /** 271 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. 272 | | */ 273 | | function latest(Trace224 storage self) internal view returns (uint224) { 274 | | uint256 pos = self._checkpoints.length; 275 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 276 | | } 277 | | 278 | | /** 279 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value 280 | | * in the most recent checkpoint. 281 | | */ 282 | | function latestCheckpoint(Trace224 storage self) internal view returns (bool exists, uint32 _key, uint224 _value) { 283 | | uint256 pos = self._checkpoints.length; 284 | | if (pos == 0) { 285 | | return (false, 0, 0); 286 | | } else { 287 | | Checkpoint224 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1); 288 | | return (true, ckpt._key, ckpt._value); 289 | | } 290 | | } 291 | | 292 | | /** 293 | | * @dev Returns the number of checkpoint. 294 | | */ 295 | | function length(Trace224 storage self) internal view returns (uint256) { 296 | | return self._checkpoints.length; 297 | | } 298 | | 299 | | /** 300 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, 301 | | * or by updating the last one. 302 | | */ 303 | | function _insert(Checkpoint224[] storage self, uint32 key, uint224 value) private returns (uint224, uint224) { 304 | | uint256 pos = self.length; 305 | | 306 | | if (pos > 0) { 307 | | // Copying to memory is important here. 308 | | Checkpoint224 memory last = _unsafeAccess(self, pos - 1); 309 | | 310 | | // Checkpoint keys must be non-decreasing. 311 | | require(last._key <= key, "Checkpoint: decreasing keys"); 312 | | 313 | | // Update or push new checkpoint 314 | | if (last._key == key) { 315 | | _unsafeAccess(self, pos - 1)._value = value; 316 | | } else { 317 | | self.push(Checkpoint224({_key: key, _value: value})); 318 | | } 319 | | return (last._value, value); 320 | | } else { 321 | | self.push(Checkpoint224({_key: key, _value: value})); 322 | | return (0, value); 323 | | } 324 | | } 325 | | 326 | | /** 327 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none. 328 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 329 | | * 330 | | * WARNING: `high` should not be greater than the array's length. 331 | | */ 332 | | function _upperBinaryLookup( 333 | | Checkpoint224[] storage self, 334 | | uint32 key, 335 | | uint256 low, 336 | | uint256 high 337 | | ) private view returns (uint256) { 338 | | while (low < high) { 339 | | uint256 mid = Math.average(low, high); 340 | | if (_unsafeAccess(self, mid)._key > key) { 341 | | high = mid; 342 | | } else { 343 | | low = mid + 1; 344 | | } 345 | | } 346 | | return high; 347 | | } 348 | | 349 | | /** 350 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none. 351 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 352 | | * 353 | | * WARNING: `high` should not be greater than the array's length. 354 | | */ 355 | | function _lowerBinaryLookup( 356 | | Checkpoint224[] storage self, 357 | | uint32 key, 358 | | uint256 low, 359 | | uint256 high 360 | | ) private view returns (uint256) { 361 | | while (low < high) { 362 | | uint256 mid = Math.average(low, high); 363 | | if (_unsafeAccess(self, mid)._key < key) { 364 | | low = mid + 1; 365 | | } else { 366 | | high = mid; 367 | | } 368 | | } 369 | | return high; 370 | | } 371 | | 372 | | /** 373 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. 374 | | */ 375 | | function _unsafeAccess( 376 | | Checkpoint224[] storage self, 377 | | uint256 pos 378 | | ) private pure returns (Checkpoint224 storage result) { 379 | | assembly { 380 | | mstore(0, self.slot) 381 | | result.slot := add(keccak256(0, 0x20), pos) 382 | | } 383 | | } 384 | | 385 | | struct Trace160 { 386 | | Checkpoint160[] _checkpoints; 387 | | } 388 | | 389 | | struct Checkpoint160 { 390 | | uint96 _key; 391 | | uint160 _value; 392 | | } 393 | | 394 | | /** 395 | | * @dev Pushes a (`key`, `value`) pair into a Trace160 so that it is stored as the checkpoint. 396 | | * 397 | | * Returns previous value and new value. 398 | | */ 399 | | function push(Trace160 storage self, uint96 key, uint160 value) internal returns (uint160, uint160) { 400 | | return _insert(self._checkpoints, key, value); 401 | | } 402 | | 403 | | /** 404 | | * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if there is none. 405 | | */ 406 | | function lowerLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { 407 | | uint256 len = self._checkpoints.length; 408 | | uint256 pos = _lowerBinaryLookup(self._checkpoints, key, 0, len); 409 | | return pos == len ? 0 : _unsafeAccess(self._checkpoints, pos)._value; 410 | | } 411 | | 412 | | /** 413 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none. 414 | | */ 415 | | function upperLookup(Trace160 storage self, uint96 key) internal view returns (uint160) { 416 | | uint256 len = self._checkpoints.length; 417 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, 0, len); 418 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 419 | | } 420 | | 421 | | /** 422 | | * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero if there is none. 423 | | * 424 | | * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys). 425 | | */ 426 | | function upperLookupRecent(Trace160 storage self, uint96 key) internal view returns (uint160) { 427 | | uint256 len = self._checkpoints.length; 428 | | 429 | | uint256 low = 0; 430 | | uint256 high = len; 431 | | 432 | | if (len > 5) { 433 | | uint256 mid = len - Math.sqrt(len); 434 | | if (key < _unsafeAccess(self._checkpoints, mid)._key) { 435 | | high = mid; 436 | | } else { 437 | | low = mid + 1; 438 | | } 439 | | } 440 | | 441 | | uint256 pos = _upperBinaryLookup(self._checkpoints, key, low, high); 442 | | 443 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 444 | | } 445 | | 446 | | /** 447 | | * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints. 448 | | */ 449 | | function latest(Trace160 storage self) internal view returns (uint160) { 450 | | uint256 pos = self._checkpoints.length; 451 | | return pos == 0 ? 0 : _unsafeAccess(self._checkpoints, pos - 1)._value; 452 | | } 453 | | 454 | | /** 455 | | * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value 456 | | * in the most recent checkpoint. 457 | | */ 458 | | function latestCheckpoint(Trace160 storage self) internal view returns (bool exists, uint96 _key, uint160 _value) { 459 | | uint256 pos = self._checkpoints.length; 460 | | if (pos == 0) { 461 | | return (false, 0, 0); 462 | | } else { 463 | | Checkpoint160 memory ckpt = _unsafeAccess(self._checkpoints, pos - 1); 464 | | return (true, ckpt._key, ckpt._value); 465 | | } 466 | | } 467 | | 468 | | /** 469 | | * @dev Returns the number of checkpoint. 470 | | */ 471 | | function length(Trace160 storage self) internal view returns (uint256) { 472 | | return self._checkpoints.length; 473 | | } 474 | | 475 | | /** 476 | | * @dev Pushes a (`key`, `value`) pair into an ordered list of checkpoints, either by inserting a new checkpoint, 477 | | * or by updating the last one. 478 | | */ 479 | | function _insert(Checkpoint160[] storage self, uint96 key, uint160 value) private returns (uint160, uint160) { 480 | | uint256 pos = self.length; 481 | | 482 | | if (pos > 0) { 483 | | // Copying to memory is important here. 484 | | Checkpoint160 memory last = _unsafeAccess(self, pos - 1); 485 | | 486 | | // Checkpoint keys must be non-decreasing. 487 | | require(last._key <= key, "Checkpoint: decreasing keys"); 488 | | 489 | | // Update or push new checkpoint 490 | | if (last._key == key) { 491 | | _unsafeAccess(self, pos - 1)._value = value; 492 | | } else { 493 | | self.push(Checkpoint160({_key: key, _value: value})); 494 | | } 495 | | return (last._value, value); 496 | | } else { 497 | | self.push(Checkpoint160({_key: key, _value: value})); 498 | | return (0, value); 499 | | } 500 | | } 501 | | 502 | | /** 503 | | * @dev Return the index of the last (most recent) checkpoint with key lower or equal than the search key, or `high` if there is none. 504 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 505 | | * 506 | | * WARNING: `high` should not be greater than the array's length. 507 | | */ 508 | | function _upperBinaryLookup( 509 | | Checkpoint160[] storage self, 510 | | uint96 key, 511 | | uint256 low, 512 | | uint256 high 513 | | ) private view returns (uint256) { 514 | | while (low < high) { 515 | | uint256 mid = Math.average(low, high); 516 | | if (_unsafeAccess(self, mid)._key > key) { 517 | | high = mid; 518 | | } else { 519 | | low = mid + 1; 520 | | } 521 | | } 522 | | return high; 523 | | } 524 | | 525 | | /** 526 | | * @dev Return the index of the first (oldest) checkpoint with key is greater or equal than the search key, or `high` if there is none. 527 | | * `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`. 528 | | * 529 | | * WARNING: `high` should not be greater than the array's length. 530 | | */ 531 | | function _lowerBinaryLookup( 532 | | Checkpoint160[] storage self, 533 | | uint96 key, 534 | | uint256 low, 535 | | uint256 high 536 | | ) private view returns (uint256) { 537 | | while (low < high) { 538 | | uint256 mid = Math.average(low, high); 539 | | if (_unsafeAccess(self, mid)._key < key) { 540 | | low = mid + 1; 541 | | } else { 542 | | high = mid; 543 | | } 544 | | } 545 | | return high; 546 | | } 547 | | 548 | | /** 549 | | * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. 550 | | */ 551 | | function _unsafeAccess( 552 | | Checkpoint160[] storage self, 553 | | uint256 pos 554 | | ) private pure returns (Checkpoint160 storage result) { 555 | | assembly { 556 | | mstore(0, self.slot) 557 | | result.slot := add(keccak256(0, 0x20), pos) 558 | | } 559 | | } 560 | | } 561 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Context.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Provides information about the current execution context, including the 8 | | * sender of the transaction and its data. While these are generally available 9 | | * via msg.sender and msg.data, they should not be accessed in such a direct 10 | | * manner, since when dealing with meta-transactions the account sending and 11 | | * paying for execution may not be the actual sender (as far as an application 12 | | * is concerned). 13 | | * 14 | | * This contract is only required for intermediate, library-like contracts. 15 | | */ 16 | | abstract contract Context { 17 | * | function _msgSender() internal view virtual returns (address) { 18 | * | return msg.sender; 19 | | } 20 | | 21 | | function _msgData() internal view virtual returns (bytes calldata) { 22 | | return msg.data; 23 | | } 24 | | } 25 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Counters.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @title Counters 8 | | * @author Matt Condon (@shrugs) 9 | | * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number 10 | | * of elements in a mapping, issuing ERC721 ids, or counting request ids. 11 | | * 12 | | * Include with `using Counters for Counters.Counter;` 13 | | */ 14 | * | library Counters { 15 | | struct Counter { 16 | | // This variable should never be directly accessed by users of the library: interactions must be restricted to 17 | | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add 18 | | // this feature: see https://github.com/ethereum/solidity/issues/4637 19 | | uint256 _value; // default: 0 20 | | } 21 | | 22 | | function current(Counter storage counter) internal view returns (uint256) { 23 | | return counter._value; 24 | | } 25 | | 26 | | function increment(Counter storage counter) internal { 27 | | unchecked { 28 | | counter._value += 1; 29 | | } 30 | | } 31 | | 32 | | function decrement(Counter storage counter) internal { 33 | | uint256 value = counter._value; 34 | | require(value > 0, "Counter: decrement overflow"); 35 | | unchecked { 36 | | counter._value = value - 1; 37 | | } 38 | | } 39 | | 40 | | function reset(Counter storage counter) internal { 41 | | counter._value = 0; 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/ShortStrings.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/ShortStrings.sol) 3 | | 4 | | pragma solidity ^0.8.8; 5 | | 6 | | import "./StorageSlot.sol"; 7 | | 8 | | // | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA | 9 | | // | length | 0x BB | 10 | | type ShortString is bytes32; 11 | | 12 | | /** 13 | | * @dev This library provides functions to convert short memory strings 14 | | * into a `ShortString` type that can be used as an immutable variable. 15 | | * 16 | | * Strings of arbitrary length can be optimized using this library if 17 | | * they are short enough (up to 31 bytes) by packing them with their 18 | | * length (1 byte) in a single EVM word (32 bytes). Additionally, a 19 | | * fallback mechanism can be used for every other case. 20 | | * 21 | | * Usage example: 22 | | * 23 | | * ```solidity 24 | | * contract Named { 25 | | * using ShortStrings for *; 26 | | * 27 | | * ShortString private immutable _name; 28 | | * string private _nameFallback; 29 | | * 30 | | * constructor(string memory contractName) { 31 | | * _name = contractName.toShortStringWithFallback(_nameFallback); 32 | | * } 33 | | * 34 | | * function name() external view returns (string memory) { 35 | | * return _name.toStringWithFallback(_nameFallback); 36 | | * } 37 | | * } 38 | | * ``` 39 | | */ 40 | * | library ShortStrings { 41 | | // Used as an identifier for strings longer than 31 bytes. 42 | | bytes32 private constant _FALLBACK_SENTINEL = 0x00000000000000000000000000000000000000000000000000000000000000FF; 43 | | 44 | | error StringTooLong(string str); 45 | | error InvalidShortString(); 46 | | 47 | | /** 48 | | * @dev Encode a string of at most 31 chars into a `ShortString`. 49 | | * 50 | | * This will trigger a `StringTooLong` error is the input string is too long. 51 | | */ 52 | | function toShortString(string memory str) internal pure returns (ShortString) { 53 | | bytes memory bstr = bytes(str); 54 | | if (bstr.length > 31) { 55 | | revert StringTooLong(str); 56 | | } 57 | | return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length)); 58 | | } 59 | | 60 | | /** 61 | | * @dev Decode a `ShortString` back to a "normal" string. 62 | | */ 63 | | function toString(ShortString sstr) internal pure returns (string memory) { 64 | | uint256 len = byteLength(sstr); 65 | | // using `new string(len)` would work locally but is not memory safe. 66 | | string memory str = new string(32); 67 | | /// @solidity memory-safe-assembly 68 | | assembly { 69 | | mstore(str, len) 70 | | mstore(add(str, 0x20), sstr) 71 | | } 72 | | return str; 73 | | } 74 | | 75 | | /** 76 | | * @dev Return the length of a `ShortString`. 77 | | */ 78 | | function byteLength(ShortString sstr) internal pure returns (uint256) { 79 | | uint256 result = uint256(ShortString.unwrap(sstr)) & 0xFF; 80 | | if (result > 31) { 81 | | revert InvalidShortString(); 82 | | } 83 | | return result; 84 | | } 85 | | 86 | | /** 87 | | * @dev Encode a string into a `ShortString`, or write it to storage if it is too long. 88 | | */ 89 | | function toShortStringWithFallback(string memory value, string storage store) internal returns (ShortString) { 90 | | if (bytes(value).length < 32) { 91 | | return toShortString(value); 92 | | } else { 93 | | StorageSlot.getStringSlot(store).value = value; 94 | | return ShortString.wrap(_FALLBACK_SENTINEL); 95 | | } 96 | | } 97 | | 98 | | /** 99 | | * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}. 100 | | */ 101 | | function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) { 102 | | if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { 103 | | return toString(value); 104 | | } else { 105 | | return store; 106 | | } 107 | | } 108 | | 109 | | /** 110 | | * @dev Return the length of a string that was encoded to `ShortString` or written to storage using {setWithFallback}. 111 | | * 112 | | * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of 113 | | * actual characters as the UTF-8 encoding of a single character can span over multiple bytes. 114 | | */ 115 | | function byteLengthWithFallback(ShortString value, string storage store) internal view returns (uint256) { 116 | | if (ShortString.unwrap(value) != _FALLBACK_SENTINEL) { 117 | | return byteLength(value); 118 | | } else { 119 | | return bytes(store).length; 120 | | } 121 | | } 122 | | } 123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/StorageSlot.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) 3 | | // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. 4 | | 5 | | pragma solidity ^0.8.0; 6 | | 7 | | /** 8 | | * @dev Library for reading and writing primitive types to specific storage slots. 9 | | * 10 | | * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. 11 | | * This library helps with reading and writing to such slots without the need for inline assembly. 12 | | * 13 | | * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. 14 | | * 15 | | * Example usage to set ERC1967 implementation slot: 16 | | * ```solidity 17 | | * contract ERC1967 { 18 | | * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 19 | | * 20 | | * function _getImplementation() internal view returns (address) { 21 | | * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; 22 | | * } 23 | | * 24 | | * function _setImplementation(address newImplementation) internal { 25 | | * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); 26 | | * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; 27 | | * } 28 | | * } 29 | | * ``` 30 | | * 31 | | * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ 32 | | * _Available since v4.9 for `string`, `bytes`._ 33 | | */ 34 | * | library StorageSlot { 35 | | struct AddressSlot { 36 | | address value; 37 | | } 38 | | 39 | | struct BooleanSlot { 40 | | bool value; 41 | | } 42 | | 43 | | struct Bytes32Slot { 44 | | bytes32 value; 45 | | } 46 | | 47 | | struct Uint256Slot { 48 | | uint256 value; 49 | | } 50 | | 51 | | struct StringSlot { 52 | | string value; 53 | | } 54 | | 55 | | struct BytesSlot { 56 | | bytes value; 57 | | } 58 | | 59 | | /** 60 | | * @dev Returns an `AddressSlot` with member `value` located at `slot`. 61 | | */ 62 | * | function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { 63 | | /// @solidity memory-safe-assembly 64 | | assembly { 65 | * | r.slot := slot 66 | | } 67 | | } 68 | | 69 | | /** 70 | | * @dev Returns an `BooleanSlot` with member `value` located at `slot`. 71 | | */ 72 | | function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { 73 | | /// @solidity memory-safe-assembly 74 | | assembly { 75 | | r.slot := slot 76 | | } 77 | | } 78 | | 79 | | /** 80 | | * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. 81 | | */ 82 | | function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { 83 | | /// @solidity memory-safe-assembly 84 | | assembly { 85 | | r.slot := slot 86 | | } 87 | | } 88 | | 89 | | /** 90 | | * @dev Returns an `Uint256Slot` with member `value` located at `slot`. 91 | | */ 92 | | function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { 93 | | /// @solidity memory-safe-assembly 94 | | assembly { 95 | | r.slot := slot 96 | | } 97 | | } 98 | | 99 | | /** 100 | | * @dev Returns an `StringSlot` with member `value` located at `slot`. 101 | | */ 102 | | function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { 103 | | /// @solidity memory-safe-assembly 104 | | assembly { 105 | | r.slot := slot 106 | | } 107 | | } 108 | | 109 | | /** 110 | | * @dev Returns an `StringSlot` representation of the string storage pointer `store`. 111 | | */ 112 | | function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { 113 | | /// @solidity memory-safe-assembly 114 | | assembly { 115 | | r.slot := store.slot 116 | | } 117 | | } 118 | | 119 | | /** 120 | | * @dev Returns an `BytesSlot` with member `value` located at `slot`. 121 | | */ 122 | | function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { 123 | | /// @solidity memory-safe-assembly 124 | | assembly { 125 | | r.slot := slot 126 | | } 127 | | } 128 | | 129 | | /** 130 | | * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. 131 | | */ 132 | | function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { 133 | | /// @solidity memory-safe-assembly 134 | | assembly { 135 | | r.slot := store.slot 136 | | } 137 | | } 138 | | } 139 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/Strings.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./math/Math.sol"; 7 | | import "./math/SignedMath.sol"; 8 | | 9 | | /** 10 | | * @dev String operations. 11 | | */ 12 | * | library Strings { 13 | | bytes16 private constant _SYMBOLS = "0123456789abcdef"; 14 | | uint8 private constant _ADDRESS_LENGTH = 20; 15 | | 16 | | /** 17 | | * @dev Converts a `uint256` to its ASCII `string` decimal representation. 18 | | */ 19 | | function toString(uint256 value) internal pure returns (string memory) { 20 | | unchecked { 21 | | uint256 length = Math.log10(value) + 1; 22 | | string memory buffer = new string(length); 23 | | uint256 ptr; 24 | | /// @solidity memory-safe-assembly 25 | | assembly { 26 | | ptr := add(buffer, add(32, length)) 27 | | } 28 | | while (true) { 29 | | ptr--; 30 | | /// @solidity memory-safe-assembly 31 | | assembly { 32 | | mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) 33 | | } 34 | | value /= 10; 35 | | if (value == 0) break; 36 | | } 37 | | return buffer; 38 | | } 39 | | } 40 | | 41 | | /** 42 | | * @dev Converts a `int256` to its ASCII `string` decimal representation. 43 | | */ 44 | | function toString(int256 value) internal pure returns (string memory) { 45 | | return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); 46 | | } 47 | | 48 | | /** 49 | | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. 50 | | */ 51 | | function toHexString(uint256 value) internal pure returns (string memory) { 52 | | unchecked { 53 | | return toHexString(value, Math.log256(value) + 1); 54 | | } 55 | | } 56 | | 57 | | /** 58 | | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. 59 | | */ 60 | | function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 61 | | bytes memory buffer = new bytes(2 * length + 2); 62 | | buffer[0] = "0"; 63 | | buffer[1] = "x"; 64 | | for (uint256 i = 2 * length + 1; i > 1; --i) { 65 | | buffer[i] = _SYMBOLS[value & 0xf]; 66 | | value >>= 4; 67 | | } 68 | | require(value == 0, "Strings: hex length insufficient"); 69 | | return string(buffer); 70 | | } 71 | | 72 | | /** 73 | | * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. 74 | | */ 75 | | function toHexString(address addr) internal pure returns (string memory) { 76 | | return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); 77 | | } 78 | | 79 | | /** 80 | | * @dev Returns true if the two strings are equal. 81 | | */ 82 | | function equal(string memory a, string memory b) internal pure returns (bool) { 83 | | return keccak256(bytes(a)) == keccak256(bytes(b)); 84 | | } 85 | | } 86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/cryptography/ECDSA.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../Strings.sol"; 7 | | 8 | | /** 9 | | * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. 10 | | * 11 | | * These functions can be used to verify that a message was signed by the holder 12 | | * of the private keys of a given address. 13 | | */ 14 | * | library ECDSA { 15 | | enum RecoverError { 16 | | NoError, 17 | | InvalidSignature, 18 | | InvalidSignatureLength, 19 | | InvalidSignatureS, 20 | | InvalidSignatureV // Deprecated in v4.8 21 | | } 22 | | 23 | | function _throwError(RecoverError error) private pure { 24 | | if (error == RecoverError.NoError) { 25 | | return; // no error: do nothing 26 | | } else if (error == RecoverError.InvalidSignature) { 27 | | revert("ECDSA: invalid signature"); 28 | | } else if (error == RecoverError.InvalidSignatureLength) { 29 | | revert("ECDSA: invalid signature length"); 30 | | } else if (error == RecoverError.InvalidSignatureS) { 31 | | revert("ECDSA: invalid signature 's' value"); 32 | | } 33 | | } 34 | | 35 | | /** 36 | | * @dev Returns the address that signed a hashed message (`hash`) with 37 | | * `signature` or error string. This address can then be used for verification purposes. 38 | | * 39 | | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 40 | | * this function rejects them by requiring the `s` value to be in the lower 41 | | * half order, and the `v` value to be either 27 or 28. 42 | | * 43 | | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 44 | | * verification to be secure: it is possible to craft signatures that 45 | | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 46 | | * this is by receiving a hash of the original message (which may otherwise 47 | | * be too long), and then calling {toEthSignedMessageHash} on it. 48 | | * 49 | | * Documentation for signature generation: 50 | | * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] 51 | | * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] 52 | | * 53 | | * _Available since v4.3._ 54 | | */ 55 | | function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { 56 | | if (signature.length == 65) { 57 | | bytes32 r; 58 | | bytes32 s; 59 | | uint8 v; 60 | | // ecrecover takes the signature parameters, and the only way to get them 61 | | // currently is to use assembly. 62 | | /// @solidity memory-safe-assembly 63 | | assembly { 64 | | r := mload(add(signature, 0x20)) 65 | | s := mload(add(signature, 0x40)) 66 | | v := byte(0, mload(add(signature, 0x60))) 67 | | } 68 | | return tryRecover(hash, v, r, s); 69 | | } else { 70 | | return (address(0), RecoverError.InvalidSignatureLength); 71 | | } 72 | | } 73 | | 74 | | /** 75 | | * @dev Returns the address that signed a hashed message (`hash`) with 76 | | * `signature`. This address can then be used for verification purposes. 77 | | * 78 | | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 79 | | * this function rejects them by requiring the `s` value to be in the lower 80 | | * half order, and the `v` value to be either 27 or 28. 81 | | * 82 | | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 83 | | * verification to be secure: it is possible to craft signatures that 84 | | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 85 | | * this is by receiving a hash of the original message (which may otherwise 86 | | * be too long), and then calling {toEthSignedMessageHash} on it. 87 | | */ 88 | | function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { 89 | | (address recovered, RecoverError error) = tryRecover(hash, signature); 90 | | _throwError(error); 91 | | return recovered; 92 | | } 93 | | 94 | | /** 95 | | * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. 96 | | * 97 | | * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] 98 | | * 99 | | * _Available since v4.3._ 100 | | */ 101 | | function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { 102 | | bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 103 | | uint8 v = uint8((uint256(vs) >> 255) + 27); 104 | | return tryRecover(hash, v, r, s); 105 | | } 106 | | 107 | | /** 108 | | * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. 109 | | * 110 | | * _Available since v4.2._ 111 | | */ 112 | | function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { 113 | | (address recovered, RecoverError error) = tryRecover(hash, r, vs); 114 | | _throwError(error); 115 | | return recovered; 116 | | } 117 | | 118 | | /** 119 | | * @dev Overload of {ECDSA-tryRecover} that receives the `v`, 120 | | * `r` and `s` signature fields separately. 121 | | * 122 | | * _Available since v4.3._ 123 | | */ 124 | | function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { 125 | | // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature 126 | | // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines 127 | | // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most 128 | | // signatures from current libraries generate a unique signature with an s-value in the lower half order. 129 | | // 130 | | // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value 131 | | // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or 132 | | // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept 133 | | // these malleable signatures as well. 134 | | if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { 135 | | return (address(0), RecoverError.InvalidSignatureS); 136 | | } 137 | | 138 | | // If the signature is valid (and not malleable), return the signer address 139 | | address signer = ecrecover(hash, v, r, s); 140 | | if (signer == address(0)) { 141 | | return (address(0), RecoverError.InvalidSignature); 142 | | } 143 | | 144 | | return (signer, RecoverError.NoError); 145 | | } 146 | | 147 | | /** 148 | | * @dev Overload of {ECDSA-recover} that receives the `v`, 149 | | * `r` and `s` signature fields separately. 150 | | */ 151 | | function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { 152 | | (address recovered, RecoverError error) = tryRecover(hash, v, r, s); 153 | | _throwError(error); 154 | | return recovered; 155 | | } 156 | | 157 | | /** 158 | | * @dev Returns an Ethereum Signed Message, created from a `hash`. This 159 | | * produces hash corresponding to the one signed with the 160 | | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 161 | | * JSON-RPC method as part of EIP-191. 162 | | * 163 | | * See {recover}. 164 | | */ 165 | | function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { 166 | | // 32 is the length in bytes of hash, 167 | | // enforced by the type signature above 168 | | /// @solidity memory-safe-assembly 169 | | assembly { 170 | | mstore(0x00, "\x19Ethereum Signed Message:\n32") 171 | | mstore(0x1c, hash) 172 | | message := keccak256(0x00, 0x3c) 173 | | } 174 | | } 175 | | 176 | | /** 177 | | * @dev Returns an Ethereum Signed Message, created from `s`. This 178 | | * produces hash corresponding to the one signed with the 179 | | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 180 | | * JSON-RPC method as part of EIP-191. 181 | | * 182 | | * See {recover}. 183 | | */ 184 | | function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { 185 | | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); 186 | | } 187 | | 188 | | /** 189 | | * @dev Returns an Ethereum Signed Typed Data, created from a 190 | | * `domainSeparator` and a `structHash`. This produces hash corresponding 191 | | * to the one signed with the 192 | | * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] 193 | | * JSON-RPC method as part of EIP-712. 194 | | * 195 | | * See {recover}. 196 | | */ 197 | | function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { 198 | | /// @solidity memory-safe-assembly 199 | | assembly { 200 | | let ptr := mload(0x40) 201 | | mstore(ptr, "\x19\x01") 202 | | mstore(add(ptr, 0x02), domainSeparator) 203 | | mstore(add(ptr, 0x22), structHash) 204 | | data := keccak256(ptr, 0x42) 205 | | } 206 | | } 207 | | 208 | | /** 209 | | * @dev Returns an Ethereum Signed Data with intended validator, created from a 210 | | * `validator` and `data` according to the version 0 of EIP-191. 211 | | * 212 | | * See {recover}. 213 | | */ 214 | | function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { 215 | | return keccak256(abi.encodePacked("\x19\x00", validator, data)); 216 | | } 217 | | } 218 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) 3 | | 4 | | pragma solidity ^0.8.8; 5 | | 6 | | import "./ECDSA.sol"; 7 | | import "../ShortStrings.sol"; 8 | | import "../../interfaces/IERC5267.sol"; 9 | | 10 | | /** 11 | | * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. 12 | | * 13 | | * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, 14 | | * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding 15 | | * they need in their contracts using a combination of `abi.encode` and `keccak256`. 16 | | * 17 | | * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding 18 | | * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA 19 | | * ({_hashTypedDataV4}). 20 | | * 21 | | * The implementation of the domain separator was designed to be as efficient as possible while still properly updating 22 | | * the chain id to protect against replay attacks on an eventual fork of the chain. 23 | | * 24 | | * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method 25 | | * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. 26 | | * 27 | | * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain 28 | | * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the 29 | | * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. 30 | | * 31 | | * _Available since v3.4._ 32 | | * 33 | | * @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment 34 | | */ 35 | | abstract contract EIP712 is IERC5267 { 36 | | using ShortStrings for *; 37 | | 38 | | bytes32 private constant _TYPE_HASH = 39 | | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); 40 | | 41 | | // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to 42 | | // invalidate the cached domain separator if the chain id changes. 43 | | bytes32 private immutable _cachedDomainSeparator; 44 | | uint256 private immutable _cachedChainId; 45 | | address private immutable _cachedThis; 46 | | 47 | | bytes32 private immutable _hashedName; 48 | | bytes32 private immutable _hashedVersion; 49 | | 50 | | ShortString private immutable _name; 51 | | ShortString private immutable _version; 52 | | string private _nameFallback; 53 | | string private _versionFallback; 54 | | 55 | | /** 56 | | * @dev Initializes the domain separator and parameter caches. 57 | | * 58 | | * The meaning of `name` and `version` is specified in 59 | | * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: 60 | | * 61 | | * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. 62 | | * - `version`: the current major version of the signing domain. 63 | | * 64 | | * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart 65 | | * contract upgrade]. 66 | | */ 67 | | constructor(string memory name, string memory version) { 68 | | _name = name.toShortStringWithFallback(_nameFallback); 69 | | _version = version.toShortStringWithFallback(_versionFallback); 70 | | _hashedName = keccak256(bytes(name)); 71 | | _hashedVersion = keccak256(bytes(version)); 72 | | 73 | | _cachedChainId = block.chainid; 74 | | _cachedDomainSeparator = _buildDomainSeparator(); 75 | | _cachedThis = address(this); 76 | | } 77 | | 78 | | /** 79 | | * @dev Returns the domain separator for the current chain. 80 | | */ 81 | | function _domainSeparatorV4() internal view returns (bytes32) { 82 | | if (address(this) == _cachedThis && block.chainid == _cachedChainId) { 83 | | return _cachedDomainSeparator; 84 | | } else { 85 | | return _buildDomainSeparator(); 86 | | } 87 | | } 88 | | 89 | | function _buildDomainSeparator() private view returns (bytes32) { 90 | | return keccak256(abi.encode(_TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this))); 91 | | } 92 | | 93 | | /** 94 | | * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this 95 | | * function returns the hash of the fully encoded EIP712 message for this domain. 96 | | * 97 | | * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: 98 | | * 99 | | * ```solidity 100 | | * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( 101 | | * keccak256("Mail(address to,string contents)"), 102 | | * mailTo, 103 | | * keccak256(bytes(mailContents)) 104 | | * ))); 105 | | * address signer = ECDSA.recover(digest, signature); 106 | | * ``` 107 | | */ 108 | | function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { 109 | | return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); 110 | | } 111 | | 112 | | /** 113 | | * @dev See {EIP-5267}. 114 | | * 115 | | * _Available since v4.9._ 116 | | */ 117 | | function eip712Domain() 118 | | public 119 | | view 120 | | virtual 121 | | override 122 | | returns ( 123 | | bytes1 fields, 124 | | string memory name, 125 | | string memory version, 126 | | uint256 chainId, 127 | | address verifyingContract, 128 | | bytes32 salt, 129 | | uint256[] memory extensions 130 | | ) 131 | | { 132 | | return ( 133 | | hex"0f", // 01111 134 | | _name.toStringWithFallback(_nameFallback), 135 | | _version.toStringWithFallback(_versionFallback), 136 | | block.chainid, 137 | | address(this), 138 | | bytes32(0), 139 | | new uint256[](0) 140 | | ); 141 | | } 142 | | } 143 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "./IERC165.sol"; 7 | | 8 | | /** 9 | | * @dev Implementation of the {IERC165} interface. 10 | | * 11 | | * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check 12 | | * for the additional interface id that will be supported. For example: 13 | | * 14 | | * ```solidity 15 | | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 16 | | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); 17 | | * } 18 | | * ``` 19 | | * 20 | | * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. 21 | | */ 22 | | abstract contract ERC165 is IERC165 { 23 | | /** 24 | | * @dev See {IERC165-supportsInterface}. 25 | | */ 26 | | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 27 | | return interfaceId == type(IERC165).interfaceId; 28 | | } 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Interface of the ERC165 standard, as defined in the 8 | | * https://eips.ethereum.org/EIPS/eip-165[EIP]. 9 | | * 10 | | * Implementers can declare support of contract interfaces, which can then be 11 | | * queried by others ({ERC165Checker}). 12 | | * 13 | | * For an implementation, see {ERC165}. 14 | | */ 15 | | interface IERC165 { 16 | | /** 17 | | * @dev Returns true if this contract implements the interface defined by 18 | | * `interfaceId`. See the corresponding 19 | | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] 20 | | * to learn more about how these ids are created. 21 | | * 22 | | * This function call must use less than 30 000 gas. 23 | | */ 24 | | function supportsInterface(bytes4 interfaceId) external view returns (bool); 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/Math.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Standard math utilities missing in the Solidity language. 8 | | */ 9 | * | library Math { 10 | | enum Rounding { 11 | | Down, // Toward negative infinity 12 | | Up, // Toward infinity 13 | | Zero // Toward zero 14 | | } 15 | | 16 | | /** 17 | | * @dev Returns the largest of two numbers. 18 | | */ 19 | | function max(uint256 a, uint256 b) internal pure returns (uint256) { 20 | | return a > b ? a : b; 21 | | } 22 | | 23 | | /** 24 | | * @dev Returns the smallest of two numbers. 25 | | */ 26 | | function min(uint256 a, uint256 b) internal pure returns (uint256) { 27 | | return a < b ? a : b; 28 | | } 29 | | 30 | | /** 31 | | * @dev Returns the average of two numbers. The result is rounded towards 32 | | * zero. 33 | | */ 34 | | function average(uint256 a, uint256 b) internal pure returns (uint256) { 35 | | // (a + b) / 2 can overflow. 36 | | return (a & b) + (a ^ b) / 2; 37 | | } 38 | | 39 | | /** 40 | | * @dev Returns the ceiling of the division of two numbers. 41 | | * 42 | | * This differs from standard division with `/` in that it rounds up instead 43 | | * of rounding down. 44 | | */ 45 | | function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { 46 | | // (a + b - 1) / b can overflow on addition, so we distribute. 47 | | return a == 0 ? 0 : (a - 1) / b + 1; 48 | | } 49 | | 50 | | /** 51 | | * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 52 | | * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) 53 | | * with further edits by Uniswap Labs also under MIT license. 54 | | */ 55 | * | function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { 56 | | unchecked { 57 | | // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use 58 | | // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 59 | | // variables such that product = prod1 * 2^256 + prod0. 60 | * | uint256 prod0; // Least significant 256 bits of the product 61 | * | uint256 prod1; // Most significant 256 bits of the product 62 | * | assembly { 63 | * | let mm := mulmod(x, y, not(0)) 64 | * | prod0 := mul(x, y) 65 | * | prod1 := sub(sub(mm, prod0), lt(mm, prod0)) 66 | | } 67 | | 68 | | // Handle non-overflow cases, 256 by 256 division. 69 | * | if (prod1 == 0) { 70 | | // Solidity will revert if denominator == 0, unlike the div opcode on its own. 71 | | // The surrounding unchecked block does not change this fact. 72 | | // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. 73 | * | return prod0 / denominator; 74 | | } 75 | | 76 | | // Make sure the result is less than 2^256. Also prevents denominator == 0. 77 | * | require(denominator > prod1, "Math: mulDiv overflow"); 78 | | 79 | | /////////////////////////////////////////////// 80 | | // 512 by 256 division. 81 | | /////////////////////////////////////////////// 82 | | 83 | | // Make division exact by subtracting the remainder from [prod1 prod0]. 84 | * | uint256 remainder; 85 | | assembly { 86 | | // Compute remainder using mulmod. 87 | * | remainder := mulmod(x, y, denominator) 88 | | 89 | | // Subtract 256 bit number from 512 bit number. 90 | * | prod1 := sub(prod1, gt(remainder, prod0)) 91 | * | prod0 := sub(prod0, remainder) 92 | | } 93 | | 94 | | // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. 95 | | // See https://cs.stackexchange.com/q/138556/92363. 96 | | 97 | | // Does not overflow because the denominator cannot be zero at this stage in the function. 98 | * | uint256 twos = denominator & (~denominator + 1); 99 | | assembly { 100 | | // Divide denominator by twos. 101 | * | denominator := div(denominator, twos) 102 | | 103 | | // Divide [prod1 prod0] by twos. 104 | * | prod0 := div(prod0, twos) 105 | | 106 | | // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. 107 | * | twos := add(div(sub(0, twos), twos), 1) 108 | | } 109 | | 110 | | // Shift in bits from prod1 into prod0. 111 | * | prod0 |= prod1 * twos; 112 | | 113 | | // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such 114 | | // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for 115 | | // four bits. That is, denominator * inv = 1 mod 2^4. 116 | * | uint256 inverse = (3 * denominator) ^ 2; 117 | | 118 | | // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works 119 | | // in modular arithmetic, doubling the correct bits in each step. 120 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^8 121 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^16 122 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^32 123 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^64 124 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^128 125 | * | inverse *= 2 - denominator * inverse; // inverse mod 2^256 126 | | 127 | | // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. 128 | | // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is 129 | | // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 130 | | // is no longer required. 131 | * | result = prod0 * inverse; 132 | * | return result; 133 | | } 134 | | } 135 | | 136 | | /** 137 | | * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. 138 | | */ 139 | * | function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { 140 | * | uint256 result = mulDiv(x, y, denominator); 141 | * | if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { 142 | * | result += 1; 143 | | } 144 | * | return result; 145 | | } 146 | | 147 | | /** 148 | | * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. 149 | | * 150 | | * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). 151 | | */ 152 | | function sqrt(uint256 a) internal pure returns (uint256) { 153 | | if (a == 0) { 154 | | return 0; 155 | | } 156 | | 157 | | // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. 158 | | // 159 | | // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have 160 | | // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. 161 | | // 162 | | // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` 163 | | // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` 164 | | // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` 165 | | // 166 | | // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. 167 | | uint256 result = 1 << (log2(a) >> 1); 168 | | 169 | | // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, 170 | | // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at 171 | | // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision 172 | | // into the expected uint128 result. 173 | | unchecked { 174 | | result = (result + a / result) >> 1; 175 | | result = (result + a / result) >> 1; 176 | | result = (result + a / result) >> 1; 177 | | result = (result + a / result) >> 1; 178 | | result = (result + a / result) >> 1; 179 | | result = (result + a / result) >> 1; 180 | | result = (result + a / result) >> 1; 181 | | return min(result, a / result); 182 | | } 183 | | } 184 | | 185 | | /** 186 | | * @notice Calculates sqrt(a), following the selected rounding direction. 187 | | */ 188 | | function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { 189 | | unchecked { 190 | | uint256 result = sqrt(a); 191 | | return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); 192 | | } 193 | | } 194 | | 195 | | /** 196 | | * @dev Return the log in base 2, rounded down, of a positive value. 197 | | * Returns 0 if given 0. 198 | | */ 199 | | function log2(uint256 value) internal pure returns (uint256) { 200 | | uint256 result = 0; 201 | | unchecked { 202 | | if (value >> 128 > 0) { 203 | | value >>= 128; 204 | | result += 128; 205 | | } 206 | | if (value >> 64 > 0) { 207 | | value >>= 64; 208 | | result += 64; 209 | | } 210 | | if (value >> 32 > 0) { 211 | | value >>= 32; 212 | | result += 32; 213 | | } 214 | | if (value >> 16 > 0) { 215 | | value >>= 16; 216 | | result += 16; 217 | | } 218 | | if (value >> 8 > 0) { 219 | | value >>= 8; 220 | | result += 8; 221 | | } 222 | | if (value >> 4 > 0) { 223 | | value >>= 4; 224 | | result += 4; 225 | | } 226 | | if (value >> 2 > 0) { 227 | | value >>= 2; 228 | | result += 2; 229 | | } 230 | | if (value >> 1 > 0) { 231 | | result += 1; 232 | | } 233 | | } 234 | | return result; 235 | | } 236 | | 237 | | /** 238 | | * @dev Return the log in base 2, following the selected rounding direction, of a positive value. 239 | | * Returns 0 if given 0. 240 | | */ 241 | | function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { 242 | | unchecked { 243 | | uint256 result = log2(value); 244 | | return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); 245 | | } 246 | | } 247 | | 248 | | /** 249 | | * @dev Return the log in base 10, rounded down, of a positive value. 250 | | * Returns 0 if given 0. 251 | | */ 252 | | function log10(uint256 value) internal pure returns (uint256) { 253 | | uint256 result = 0; 254 | | unchecked { 255 | | if (value >= 10 ** 64) { 256 | | value /= 10 ** 64; 257 | | result += 64; 258 | | } 259 | | if (value >= 10 ** 32) { 260 | | value /= 10 ** 32; 261 | | result += 32; 262 | | } 263 | | if (value >= 10 ** 16) { 264 | | value /= 10 ** 16; 265 | | result += 16; 266 | | } 267 | | if (value >= 10 ** 8) { 268 | | value /= 10 ** 8; 269 | | result += 8; 270 | | } 271 | | if (value >= 10 ** 4) { 272 | | value /= 10 ** 4; 273 | | result += 4; 274 | | } 275 | | if (value >= 10 ** 2) { 276 | | value /= 10 ** 2; 277 | | result += 2; 278 | | } 279 | | if (value >= 10 ** 1) { 280 | | result += 1; 281 | | } 282 | | } 283 | | return result; 284 | | } 285 | | 286 | | /** 287 | | * @dev Return the log in base 10, following the selected rounding direction, of a positive value. 288 | | * Returns 0 if given 0. 289 | | */ 290 | | function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { 291 | | unchecked { 292 | | uint256 result = log10(value); 293 | | return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); 294 | | } 295 | | } 296 | | 297 | | /** 298 | | * @dev Return the log in base 256, rounded down, of a positive value. 299 | | * Returns 0 if given 0. 300 | | * 301 | | * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. 302 | | */ 303 | | function log256(uint256 value) internal pure returns (uint256) { 304 | | uint256 result = 0; 305 | | unchecked { 306 | | if (value >> 128 > 0) { 307 | | value >>= 128; 308 | | result += 16; 309 | | } 310 | | if (value >> 64 > 0) { 311 | | value >>= 64; 312 | | result += 8; 313 | | } 314 | | if (value >> 32 > 0) { 315 | | value >>= 32; 316 | | result += 4; 317 | | } 318 | | if (value >> 16 > 0) { 319 | | value >>= 16; 320 | | result += 2; 321 | | } 322 | | if (value >> 8 > 0) { 323 | | result += 1; 324 | | } 325 | | } 326 | | return result; 327 | | } 328 | | 329 | | /** 330 | | * @dev Return the log in base 256, following the selected rounding direction, of a positive value. 331 | | * Returns 0 if given 0. 332 | | */ 333 | | function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { 334 | | unchecked { 335 | | uint256 result = log256(value); 336 | | return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); 337 | | } 338 | | } 339 | | } 340 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol) 3 | | // This file was procedurally generated from scripts/generate/templates/SafeCast.js. 4 | | 5 | | pragma solidity ^0.8.0; 6 | | 7 | | /** 8 | | * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow 9 | | * checks. 10 | | * 11 | | * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can 12 | | * easily result in undesired exploitation or bugs, since developers usually 13 | | * assume that overflows raise errors. `SafeCast` restores this intuition by 14 | | * reverting the transaction when such an operation overflows. 15 | | * 16 | | * Using this library instead of the unchecked operations eliminates an entire 17 | | * class of bugs, so it's recommended to use it always. 18 | | * 19 | | * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing 20 | | * all math on `uint256` and `int256` and then downcasting. 21 | | */ 22 | * | library SafeCast { 23 | | /** 24 | | * @dev Returns the downcasted uint248 from uint256, reverting on 25 | | * overflow (when the input is greater than largest uint248). 26 | | * 27 | | * Counterpart to Solidity's `uint248` operator. 28 | | * 29 | | * Requirements: 30 | | * 31 | | * - input must fit into 248 bits 32 | | * 33 | | * _Available since v4.7._ 34 | | */ 35 | | function toUint248(uint256 value) internal pure returns (uint248) { 36 | | require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); 37 | | return uint248(value); 38 | | } 39 | | 40 | | /** 41 | | * @dev Returns the downcasted uint240 from uint256, reverting on 42 | | * overflow (when the input is greater than largest uint240). 43 | | * 44 | | * Counterpart to Solidity's `uint240` operator. 45 | | * 46 | | * Requirements: 47 | | * 48 | | * - input must fit into 240 bits 49 | | * 50 | | * _Available since v4.7._ 51 | | */ 52 | | function toUint240(uint256 value) internal pure returns (uint240) { 53 | | require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); 54 | | return uint240(value); 55 | | } 56 | | 57 | | /** 58 | | * @dev Returns the downcasted uint232 from uint256, reverting on 59 | | * overflow (when the input is greater than largest uint232). 60 | | * 61 | | * Counterpart to Solidity's `uint232` operator. 62 | | * 63 | | * Requirements: 64 | | * 65 | | * - input must fit into 232 bits 66 | | * 67 | | * _Available since v4.7._ 68 | | */ 69 | | function toUint232(uint256 value) internal pure returns (uint232) { 70 | | require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); 71 | | return uint232(value); 72 | | } 73 | | 74 | | /** 75 | | * @dev Returns the downcasted uint224 from uint256, reverting on 76 | | * overflow (when the input is greater than largest uint224). 77 | | * 78 | | * Counterpart to Solidity's `uint224` operator. 79 | | * 80 | | * Requirements: 81 | | * 82 | | * - input must fit into 224 bits 83 | | * 84 | | * _Available since v4.2._ 85 | | */ 86 | | function toUint224(uint256 value) internal pure returns (uint224) { 87 | | require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); 88 | | return uint224(value); 89 | | } 90 | | 91 | | /** 92 | | * @dev Returns the downcasted uint216 from uint256, reverting on 93 | | * overflow (when the input is greater than largest uint216). 94 | | * 95 | | * Counterpart to Solidity's `uint216` operator. 96 | | * 97 | | * Requirements: 98 | | * 99 | | * - input must fit into 216 bits 100 | | * 101 | | * _Available since v4.7._ 102 | | */ 103 | | function toUint216(uint256 value) internal pure returns (uint216) { 104 | | require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); 105 | | return uint216(value); 106 | | } 107 | | 108 | | /** 109 | | * @dev Returns the downcasted uint208 from uint256, reverting on 110 | | * overflow (when the input is greater than largest uint208). 111 | | * 112 | | * Counterpart to Solidity's `uint208` operator. 113 | | * 114 | | * Requirements: 115 | | * 116 | | * - input must fit into 208 bits 117 | | * 118 | | * _Available since v4.7._ 119 | | */ 120 | | function toUint208(uint256 value) internal pure returns (uint208) { 121 | | require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); 122 | | return uint208(value); 123 | | } 124 | | 125 | | /** 126 | | * @dev Returns the downcasted uint200 from uint256, reverting on 127 | | * overflow (when the input is greater than largest uint200). 128 | | * 129 | | * Counterpart to Solidity's `uint200` operator. 130 | | * 131 | | * Requirements: 132 | | * 133 | | * - input must fit into 200 bits 134 | | * 135 | | * _Available since v4.7._ 136 | | */ 137 | | function toUint200(uint256 value) internal pure returns (uint200) { 138 | | require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); 139 | | return uint200(value); 140 | | } 141 | | 142 | | /** 143 | | * @dev Returns the downcasted uint192 from uint256, reverting on 144 | | * overflow (when the input is greater than largest uint192). 145 | | * 146 | | * Counterpart to Solidity's `uint192` operator. 147 | | * 148 | | * Requirements: 149 | | * 150 | | * - input must fit into 192 bits 151 | | * 152 | | * _Available since v4.7._ 153 | | */ 154 | | function toUint192(uint256 value) internal pure returns (uint192) { 155 | | require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); 156 | | return uint192(value); 157 | | } 158 | | 159 | | /** 160 | | * @dev Returns the downcasted uint184 from uint256, reverting on 161 | | * overflow (when the input is greater than largest uint184). 162 | | * 163 | | * Counterpart to Solidity's `uint184` operator. 164 | | * 165 | | * Requirements: 166 | | * 167 | | * - input must fit into 184 bits 168 | | * 169 | | * _Available since v4.7._ 170 | | */ 171 | | function toUint184(uint256 value) internal pure returns (uint184) { 172 | | require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); 173 | | return uint184(value); 174 | | } 175 | | 176 | | /** 177 | | * @dev Returns the downcasted uint176 from uint256, reverting on 178 | | * overflow (when the input is greater than largest uint176). 179 | | * 180 | | * Counterpart to Solidity's `uint176` operator. 181 | | * 182 | | * Requirements: 183 | | * 184 | | * - input must fit into 176 bits 185 | | * 186 | | * _Available since v4.7._ 187 | | */ 188 | | function toUint176(uint256 value) internal pure returns (uint176) { 189 | | require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); 190 | | return uint176(value); 191 | | } 192 | | 193 | | /** 194 | | * @dev Returns the downcasted uint168 from uint256, reverting on 195 | | * overflow (when the input is greater than largest uint168). 196 | | * 197 | | * Counterpart to Solidity's `uint168` operator. 198 | | * 199 | | * Requirements: 200 | | * 201 | | * - input must fit into 168 bits 202 | | * 203 | | * _Available since v4.7._ 204 | | */ 205 | | function toUint168(uint256 value) internal pure returns (uint168) { 206 | | require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); 207 | | return uint168(value); 208 | | } 209 | | 210 | | /** 211 | | * @dev Returns the downcasted uint160 from uint256, reverting on 212 | | * overflow (when the input is greater than largest uint160). 213 | | * 214 | | * Counterpart to Solidity's `uint160` operator. 215 | | * 216 | | * Requirements: 217 | | * 218 | | * - input must fit into 160 bits 219 | | * 220 | | * _Available since v4.7._ 221 | | */ 222 | | function toUint160(uint256 value) internal pure returns (uint160) { 223 | | require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); 224 | | return uint160(value); 225 | | } 226 | | 227 | | /** 228 | | * @dev Returns the downcasted uint152 from uint256, reverting on 229 | | * overflow (when the input is greater than largest uint152). 230 | | * 231 | | * Counterpart to Solidity's `uint152` operator. 232 | | * 233 | | * Requirements: 234 | | * 235 | | * - input must fit into 152 bits 236 | | * 237 | | * _Available since v4.7._ 238 | | */ 239 | | function toUint152(uint256 value) internal pure returns (uint152) { 240 | | require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); 241 | | return uint152(value); 242 | | } 243 | | 244 | | /** 245 | | * @dev Returns the downcasted uint144 from uint256, reverting on 246 | | * overflow (when the input is greater than largest uint144). 247 | | * 248 | | * Counterpart to Solidity's `uint144` operator. 249 | | * 250 | | * Requirements: 251 | | * 252 | | * - input must fit into 144 bits 253 | | * 254 | | * _Available since v4.7._ 255 | | */ 256 | | function toUint144(uint256 value) internal pure returns (uint144) { 257 | | require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); 258 | | return uint144(value); 259 | | } 260 | | 261 | | /** 262 | | * @dev Returns the downcasted uint136 from uint256, reverting on 263 | | * overflow (when the input is greater than largest uint136). 264 | | * 265 | | * Counterpart to Solidity's `uint136` operator. 266 | | * 267 | | * Requirements: 268 | | * 269 | | * - input must fit into 136 bits 270 | | * 271 | | * _Available since v4.7._ 272 | | */ 273 | | function toUint136(uint256 value) internal pure returns (uint136) { 274 | | require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); 275 | | return uint136(value); 276 | | } 277 | | 278 | | /** 279 | | * @dev Returns the downcasted uint128 from uint256, reverting on 280 | | * overflow (when the input is greater than largest uint128). 281 | | * 282 | | * Counterpart to Solidity's `uint128` operator. 283 | | * 284 | | * Requirements: 285 | | * 286 | | * - input must fit into 128 bits 287 | | * 288 | | * _Available since v2.5._ 289 | | */ 290 | | function toUint128(uint256 value) internal pure returns (uint128) { 291 | | require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); 292 | | return uint128(value); 293 | | } 294 | | 295 | | /** 296 | | * @dev Returns the downcasted uint120 from uint256, reverting on 297 | | * overflow (when the input is greater than largest uint120). 298 | | * 299 | | * Counterpart to Solidity's `uint120` operator. 300 | | * 301 | | * Requirements: 302 | | * 303 | | * - input must fit into 120 bits 304 | | * 305 | | * _Available since v4.7._ 306 | | */ 307 | | function toUint120(uint256 value) internal pure returns (uint120) { 308 | | require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); 309 | | return uint120(value); 310 | | } 311 | | 312 | | /** 313 | | * @dev Returns the downcasted uint112 from uint256, reverting on 314 | | * overflow (when the input is greater than largest uint112). 315 | | * 316 | | * Counterpart to Solidity's `uint112` operator. 317 | | * 318 | | * Requirements: 319 | | * 320 | | * - input must fit into 112 bits 321 | | * 322 | | * _Available since v4.7._ 323 | | */ 324 | | function toUint112(uint256 value) internal pure returns (uint112) { 325 | | require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); 326 | | return uint112(value); 327 | | } 328 | | 329 | | /** 330 | | * @dev Returns the downcasted uint104 from uint256, reverting on 331 | | * overflow (when the input is greater than largest uint104). 332 | | * 333 | | * Counterpart to Solidity's `uint104` operator. 334 | | * 335 | | * Requirements: 336 | | * 337 | | * - input must fit into 104 bits 338 | | * 339 | | * _Available since v4.7._ 340 | | */ 341 | | function toUint104(uint256 value) internal pure returns (uint104) { 342 | | require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); 343 | | return uint104(value); 344 | | } 345 | | 346 | | /** 347 | | * @dev Returns the downcasted uint96 from uint256, reverting on 348 | | * overflow (when the input is greater than largest uint96). 349 | | * 350 | | * Counterpart to Solidity's `uint96` operator. 351 | | * 352 | | * Requirements: 353 | | * 354 | | * - input must fit into 96 bits 355 | | * 356 | | * _Available since v4.2._ 357 | | */ 358 | | function toUint96(uint256 value) internal pure returns (uint96) { 359 | | require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); 360 | | return uint96(value); 361 | | } 362 | | 363 | | /** 364 | | * @dev Returns the downcasted uint88 from uint256, reverting on 365 | | * overflow (when the input is greater than largest uint88). 366 | | * 367 | | * Counterpart to Solidity's `uint88` operator. 368 | | * 369 | | * Requirements: 370 | | * 371 | | * - input must fit into 88 bits 372 | | * 373 | | * _Available since v4.7._ 374 | | */ 375 | | function toUint88(uint256 value) internal pure returns (uint88) { 376 | | require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); 377 | | return uint88(value); 378 | | } 379 | | 380 | | /** 381 | | * @dev Returns the downcasted uint80 from uint256, reverting on 382 | | * overflow (when the input is greater than largest uint80). 383 | | * 384 | | * Counterpart to Solidity's `uint80` operator. 385 | | * 386 | | * Requirements: 387 | | * 388 | | * - input must fit into 80 bits 389 | | * 390 | | * _Available since v4.7._ 391 | | */ 392 | | function toUint80(uint256 value) internal pure returns (uint80) { 393 | | require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); 394 | | return uint80(value); 395 | | } 396 | | 397 | | /** 398 | | * @dev Returns the downcasted uint72 from uint256, reverting on 399 | | * overflow (when the input is greater than largest uint72). 400 | | * 401 | | * Counterpart to Solidity's `uint72` operator. 402 | | * 403 | | * Requirements: 404 | | * 405 | | * - input must fit into 72 bits 406 | | * 407 | | * _Available since v4.7._ 408 | | */ 409 | | function toUint72(uint256 value) internal pure returns (uint72) { 410 | | require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); 411 | | return uint72(value); 412 | | } 413 | | 414 | | /** 415 | | * @dev Returns the downcasted uint64 from uint256, reverting on 416 | | * overflow (when the input is greater than largest uint64). 417 | | * 418 | | * Counterpart to Solidity's `uint64` operator. 419 | | * 420 | | * Requirements: 421 | | * 422 | | * - input must fit into 64 bits 423 | | * 424 | | * _Available since v2.5._ 425 | | */ 426 | | function toUint64(uint256 value) internal pure returns (uint64) { 427 | | require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); 428 | | return uint64(value); 429 | | } 430 | | 431 | | /** 432 | | * @dev Returns the downcasted uint56 from uint256, reverting on 433 | | * overflow (when the input is greater than largest uint56). 434 | | * 435 | | * Counterpart to Solidity's `uint56` operator. 436 | | * 437 | | * Requirements: 438 | | * 439 | | * - input must fit into 56 bits 440 | | * 441 | | * _Available since v4.7._ 442 | | */ 443 | | function toUint56(uint256 value) internal pure returns (uint56) { 444 | | require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); 445 | | return uint56(value); 446 | | } 447 | | 448 | | /** 449 | | * @dev Returns the downcasted uint48 from uint256, reverting on 450 | | * overflow (when the input is greater than largest uint48). 451 | | * 452 | | * Counterpart to Solidity's `uint48` operator. 453 | | * 454 | | * Requirements: 455 | | * 456 | | * - input must fit into 48 bits 457 | | * 458 | | * _Available since v4.7._ 459 | | */ 460 | | function toUint48(uint256 value) internal pure returns (uint48) { 461 | | require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); 462 | | return uint48(value); 463 | | } 464 | | 465 | | /** 466 | | * @dev Returns the downcasted uint40 from uint256, reverting on 467 | | * overflow (when the input is greater than largest uint40). 468 | | * 469 | | * Counterpart to Solidity's `uint40` operator. 470 | | * 471 | | * Requirements: 472 | | * 473 | | * - input must fit into 40 bits 474 | | * 475 | | * _Available since v4.7._ 476 | | */ 477 | | function toUint40(uint256 value) internal pure returns (uint40) { 478 | | require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); 479 | | return uint40(value); 480 | | } 481 | | 482 | | /** 483 | | * @dev Returns the downcasted uint32 from uint256, reverting on 484 | | * overflow (when the input is greater than largest uint32). 485 | | * 486 | | * Counterpart to Solidity's `uint32` operator. 487 | | * 488 | | * Requirements: 489 | | * 490 | | * - input must fit into 32 bits 491 | | * 492 | | * _Available since v2.5._ 493 | | */ 494 | | function toUint32(uint256 value) internal pure returns (uint32) { 495 | | require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); 496 | | return uint32(value); 497 | | } 498 | | 499 | | /** 500 | | * @dev Returns the downcasted uint24 from uint256, reverting on 501 | | * overflow (when the input is greater than largest uint24). 502 | | * 503 | | * Counterpart to Solidity's `uint24` operator. 504 | | * 505 | | * Requirements: 506 | | * 507 | | * - input must fit into 24 bits 508 | | * 509 | | * _Available since v4.7._ 510 | | */ 511 | | function toUint24(uint256 value) internal pure returns (uint24) { 512 | | require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); 513 | | return uint24(value); 514 | | } 515 | | 516 | | /** 517 | | * @dev Returns the downcasted uint16 from uint256, reverting on 518 | | * overflow (when the input is greater than largest uint16). 519 | | * 520 | | * Counterpart to Solidity's `uint16` operator. 521 | | * 522 | | * Requirements: 523 | | * 524 | | * - input must fit into 16 bits 525 | | * 526 | | * _Available since v2.5._ 527 | | */ 528 | | function toUint16(uint256 value) internal pure returns (uint16) { 529 | | require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); 530 | | return uint16(value); 531 | | } 532 | | 533 | | /** 534 | | * @dev Returns the downcasted uint8 from uint256, reverting on 535 | | * overflow (when the input is greater than largest uint8). 536 | | * 537 | | * Counterpart to Solidity's `uint8` operator. 538 | | * 539 | | * Requirements: 540 | | * 541 | | * - input must fit into 8 bits 542 | | * 543 | | * _Available since v2.5._ 544 | | */ 545 | | function toUint8(uint256 value) internal pure returns (uint8) { 546 | | require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); 547 | | return uint8(value); 548 | | } 549 | | 550 | | /** 551 | | * @dev Converts a signed int256 into an unsigned uint256. 552 | | * 553 | | * Requirements: 554 | | * 555 | | * - input must be greater than or equal to 0. 556 | | * 557 | | * _Available since v3.0._ 558 | | */ 559 | * | function toUint256(int256 value) internal pure returns (uint256) { 560 | * | require(value >= 0, "SafeCast: value must be positive"); 561 | * | return uint256(value); 562 | | } 563 | | 564 | | /** 565 | | * @dev Returns the downcasted int248 from int256, reverting on 566 | | * overflow (when the input is less than smallest int248 or 567 | | * greater than largest int248). 568 | | * 569 | | * Counterpart to Solidity's `int248` operator. 570 | | * 571 | | * Requirements: 572 | | * 573 | | * - input must fit into 248 bits 574 | | * 575 | | * _Available since v4.7._ 576 | | */ 577 | | function toInt248(int256 value) internal pure returns (int248 downcasted) { 578 | | downcasted = int248(value); 579 | | require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); 580 | | } 581 | | 582 | | /** 583 | | * @dev Returns the downcasted int240 from int256, reverting on 584 | | * overflow (when the input is less than smallest int240 or 585 | | * greater than largest int240). 586 | | * 587 | | * Counterpart to Solidity's `int240` operator. 588 | | * 589 | | * Requirements: 590 | | * 591 | | * - input must fit into 240 bits 592 | | * 593 | | * _Available since v4.7._ 594 | | */ 595 | | function toInt240(int256 value) internal pure returns (int240 downcasted) { 596 | | downcasted = int240(value); 597 | | require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); 598 | | } 599 | | 600 | | /** 601 | | * @dev Returns the downcasted int232 from int256, reverting on 602 | | * overflow (when the input is less than smallest int232 or 603 | | * greater than largest int232). 604 | | * 605 | | * Counterpart to Solidity's `int232` operator. 606 | | * 607 | | * Requirements: 608 | | * 609 | | * - input must fit into 232 bits 610 | | * 611 | | * _Available since v4.7._ 612 | | */ 613 | | function toInt232(int256 value) internal pure returns (int232 downcasted) { 614 | | downcasted = int232(value); 615 | | require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); 616 | | } 617 | | 618 | | /** 619 | | * @dev Returns the downcasted int224 from int256, reverting on 620 | | * overflow (when the input is less than smallest int224 or 621 | | * greater than largest int224). 622 | | * 623 | | * Counterpart to Solidity's `int224` operator. 624 | | * 625 | | * Requirements: 626 | | * 627 | | * - input must fit into 224 bits 628 | | * 629 | | * _Available since v4.7._ 630 | | */ 631 | | function toInt224(int256 value) internal pure returns (int224 downcasted) { 632 | | downcasted = int224(value); 633 | | require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); 634 | | } 635 | | 636 | | /** 637 | | * @dev Returns the downcasted int216 from int256, reverting on 638 | | * overflow (when the input is less than smallest int216 or 639 | | * greater than largest int216). 640 | | * 641 | | * Counterpart to Solidity's `int216` operator. 642 | | * 643 | | * Requirements: 644 | | * 645 | | * - input must fit into 216 bits 646 | | * 647 | | * _Available since v4.7._ 648 | | */ 649 | | function toInt216(int256 value) internal pure returns (int216 downcasted) { 650 | | downcasted = int216(value); 651 | | require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); 652 | | } 653 | | 654 | | /** 655 | | * @dev Returns the downcasted int208 from int256, reverting on 656 | | * overflow (when the input is less than smallest int208 or 657 | | * greater than largest int208). 658 | | * 659 | | * Counterpart to Solidity's `int208` operator. 660 | | * 661 | | * Requirements: 662 | | * 663 | | * - input must fit into 208 bits 664 | | * 665 | | * _Available since v4.7._ 666 | | */ 667 | | function toInt208(int256 value) internal pure returns (int208 downcasted) { 668 | | downcasted = int208(value); 669 | | require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); 670 | | } 671 | | 672 | | /** 673 | | * @dev Returns the downcasted int200 from int256, reverting on 674 | | * overflow (when the input is less than smallest int200 or 675 | | * greater than largest int200). 676 | | * 677 | | * Counterpart to Solidity's `int200` operator. 678 | | * 679 | | * Requirements: 680 | | * 681 | | * - input must fit into 200 bits 682 | | * 683 | | * _Available since v4.7._ 684 | | */ 685 | | function toInt200(int256 value) internal pure returns (int200 downcasted) { 686 | | downcasted = int200(value); 687 | | require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); 688 | | } 689 | | 690 | | /** 691 | | * @dev Returns the downcasted int192 from int256, reverting on 692 | | * overflow (when the input is less than smallest int192 or 693 | | * greater than largest int192). 694 | | * 695 | | * Counterpart to Solidity's `int192` operator. 696 | | * 697 | | * Requirements: 698 | | * 699 | | * - input must fit into 192 bits 700 | | * 701 | | * _Available since v4.7._ 702 | | */ 703 | | function toInt192(int256 value) internal pure returns (int192 downcasted) { 704 | | downcasted = int192(value); 705 | | require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); 706 | | } 707 | | 708 | | /** 709 | | * @dev Returns the downcasted int184 from int256, reverting on 710 | | * overflow (when the input is less than smallest int184 or 711 | | * greater than largest int184). 712 | | * 713 | | * Counterpart to Solidity's `int184` operator. 714 | | * 715 | | * Requirements: 716 | | * 717 | | * - input must fit into 184 bits 718 | | * 719 | | * _Available since v4.7._ 720 | | */ 721 | | function toInt184(int256 value) internal pure returns (int184 downcasted) { 722 | | downcasted = int184(value); 723 | | require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); 724 | | } 725 | | 726 | | /** 727 | | * @dev Returns the downcasted int176 from int256, reverting on 728 | | * overflow (when the input is less than smallest int176 or 729 | | * greater than largest int176). 730 | | * 731 | | * Counterpart to Solidity's `int176` operator. 732 | | * 733 | | * Requirements: 734 | | * 735 | | * - input must fit into 176 bits 736 | | * 737 | | * _Available since v4.7._ 738 | | */ 739 | | function toInt176(int256 value) internal pure returns (int176 downcasted) { 740 | | downcasted = int176(value); 741 | | require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); 742 | | } 743 | | 744 | | /** 745 | | * @dev Returns the downcasted int168 from int256, reverting on 746 | | * overflow (when the input is less than smallest int168 or 747 | | * greater than largest int168). 748 | | * 749 | | * Counterpart to Solidity's `int168` operator. 750 | | * 751 | | * Requirements: 752 | | * 753 | | * - input must fit into 168 bits 754 | | * 755 | | * _Available since v4.7._ 756 | | */ 757 | | function toInt168(int256 value) internal pure returns (int168 downcasted) { 758 | | downcasted = int168(value); 759 | | require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); 760 | | } 761 | | 762 | | /** 763 | | * @dev Returns the downcasted int160 from int256, reverting on 764 | | * overflow (when the input is less than smallest int160 or 765 | | * greater than largest int160). 766 | | * 767 | | * Counterpart to Solidity's `int160` operator. 768 | | * 769 | | * Requirements: 770 | | * 771 | | * - input must fit into 160 bits 772 | | * 773 | | * _Available since v4.7._ 774 | | */ 775 | | function toInt160(int256 value) internal pure returns (int160 downcasted) { 776 | | downcasted = int160(value); 777 | | require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); 778 | | } 779 | | 780 | | /** 781 | | * @dev Returns the downcasted int152 from int256, reverting on 782 | | * overflow (when the input is less than smallest int152 or 783 | | * greater than largest int152). 784 | | * 785 | | * Counterpart to Solidity's `int152` operator. 786 | | * 787 | | * Requirements: 788 | | * 789 | | * - input must fit into 152 bits 790 | | * 791 | | * _Available since v4.7._ 792 | | */ 793 | | function toInt152(int256 value) internal pure returns (int152 downcasted) { 794 | | downcasted = int152(value); 795 | | require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); 796 | | } 797 | | 798 | | /** 799 | | * @dev Returns the downcasted int144 from int256, reverting on 800 | | * overflow (when the input is less than smallest int144 or 801 | | * greater than largest int144). 802 | | * 803 | | * Counterpart to Solidity's `int144` operator. 804 | | * 805 | | * Requirements: 806 | | * 807 | | * - input must fit into 144 bits 808 | | * 809 | | * _Available since v4.7._ 810 | | */ 811 | | function toInt144(int256 value) internal pure returns (int144 downcasted) { 812 | | downcasted = int144(value); 813 | | require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); 814 | | } 815 | | 816 | | /** 817 | | * @dev Returns the downcasted int136 from int256, reverting on 818 | | * overflow (when the input is less than smallest int136 or 819 | | * greater than largest int136). 820 | | * 821 | | * Counterpart to Solidity's `int136` operator. 822 | | * 823 | | * Requirements: 824 | | * 825 | | * - input must fit into 136 bits 826 | | * 827 | | * _Available since v4.7._ 828 | | */ 829 | | function toInt136(int256 value) internal pure returns (int136 downcasted) { 830 | | downcasted = int136(value); 831 | | require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); 832 | | } 833 | | 834 | | /** 835 | | * @dev Returns the downcasted int128 from int256, reverting on 836 | | * overflow (when the input is less than smallest int128 or 837 | | * greater than largest int128). 838 | | * 839 | | * Counterpart to Solidity's `int128` operator. 840 | | * 841 | | * Requirements: 842 | | * 843 | | * - input must fit into 128 bits 844 | | * 845 | | * _Available since v3.1._ 846 | | */ 847 | | function toInt128(int256 value) internal pure returns (int128 downcasted) { 848 | | downcasted = int128(value); 849 | | require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); 850 | | } 851 | | 852 | | /** 853 | | * @dev Returns the downcasted int120 from int256, reverting on 854 | | * overflow (when the input is less than smallest int120 or 855 | | * greater than largest int120). 856 | | * 857 | | * Counterpart to Solidity's `int120` operator. 858 | | * 859 | | * Requirements: 860 | | * 861 | | * - input must fit into 120 bits 862 | | * 863 | | * _Available since v4.7._ 864 | | */ 865 | | function toInt120(int256 value) internal pure returns (int120 downcasted) { 866 | | downcasted = int120(value); 867 | | require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); 868 | | } 869 | | 870 | | /** 871 | | * @dev Returns the downcasted int112 from int256, reverting on 872 | | * overflow (when the input is less than smallest int112 or 873 | | * greater than largest int112). 874 | | * 875 | | * Counterpart to Solidity's `int112` operator. 876 | | * 877 | | * Requirements: 878 | | * 879 | | * - input must fit into 112 bits 880 | | * 881 | | * _Available since v4.7._ 882 | | */ 883 | | function toInt112(int256 value) internal pure returns (int112 downcasted) { 884 | | downcasted = int112(value); 885 | | require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); 886 | | } 887 | | 888 | | /** 889 | | * @dev Returns the downcasted int104 from int256, reverting on 890 | | * overflow (when the input is less than smallest int104 or 891 | | * greater than largest int104). 892 | | * 893 | | * Counterpart to Solidity's `int104` operator. 894 | | * 895 | | * Requirements: 896 | | * 897 | | * - input must fit into 104 bits 898 | | * 899 | | * _Available since v4.7._ 900 | | */ 901 | | function toInt104(int256 value) internal pure returns (int104 downcasted) { 902 | | downcasted = int104(value); 903 | | require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); 904 | | } 905 | | 906 | | /** 907 | | * @dev Returns the downcasted int96 from int256, reverting on 908 | | * overflow (when the input is less than smallest int96 or 909 | | * greater than largest int96). 910 | | * 911 | | * Counterpart to Solidity's `int96` operator. 912 | | * 913 | | * Requirements: 914 | | * 915 | | * - input must fit into 96 bits 916 | | * 917 | | * _Available since v4.7._ 918 | | */ 919 | | function toInt96(int256 value) internal pure returns (int96 downcasted) { 920 | | downcasted = int96(value); 921 | | require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); 922 | | } 923 | | 924 | | /** 925 | | * @dev Returns the downcasted int88 from int256, reverting on 926 | | * overflow (when the input is less than smallest int88 or 927 | | * greater than largest int88). 928 | | * 929 | | * Counterpart to Solidity's `int88` operator. 930 | | * 931 | | * Requirements: 932 | | * 933 | | * - input must fit into 88 bits 934 | | * 935 | | * _Available since v4.7._ 936 | | */ 937 | | function toInt88(int256 value) internal pure returns (int88 downcasted) { 938 | | downcasted = int88(value); 939 | | require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); 940 | | } 941 | | 942 | | /** 943 | | * @dev Returns the downcasted int80 from int256, reverting on 944 | | * overflow (when the input is less than smallest int80 or 945 | | * greater than largest int80). 946 | | * 947 | | * Counterpart to Solidity's `int80` operator. 948 | | * 949 | | * Requirements: 950 | | * 951 | | * - input must fit into 80 bits 952 | | * 953 | | * _Available since v4.7._ 954 | | */ 955 | | function toInt80(int256 value) internal pure returns (int80 downcasted) { 956 | | downcasted = int80(value); 957 | | require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); 958 | | } 959 | | 960 | | /** 961 | | * @dev Returns the downcasted int72 from int256, reverting on 962 | | * overflow (when the input is less than smallest int72 or 963 | | * greater than largest int72). 964 | | * 965 | | * Counterpart to Solidity's `int72` operator. 966 | | * 967 | | * Requirements: 968 | | * 969 | | * - input must fit into 72 bits 970 | | * 971 | | * _Available since v4.7._ 972 | | */ 973 | | function toInt72(int256 value) internal pure returns (int72 downcasted) { 974 | | downcasted = int72(value); 975 | | require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); 976 | | } 977 | | 978 | | /** 979 | | * @dev Returns the downcasted int64 from int256, reverting on 980 | | * overflow (when the input is less than smallest int64 or 981 | | * greater than largest int64). 982 | | * 983 | | * Counterpart to Solidity's `int64` operator. 984 | | * 985 | | * Requirements: 986 | | * 987 | | * - input must fit into 64 bits 988 | | * 989 | | * _Available since v3.1._ 990 | | */ 991 | | function toInt64(int256 value) internal pure returns (int64 downcasted) { 992 | | downcasted = int64(value); 993 | | require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); 994 | | } 995 | | 996 | | /** 997 | | * @dev Returns the downcasted int56 from int256, reverting on 998 | | * overflow (when the input is less than smallest int56 or 999 | | * greater than largest int56). 1000 | | * 1001 | | * Counterpart to Solidity's `int56` operator. 1002 | | * 1003 | | * Requirements: 1004 | | * 1005 | | * - input must fit into 56 bits 1006 | | * 1007 | | * _Available since v4.7._ 1008 | | */ 1009 | | function toInt56(int256 value) internal pure returns (int56 downcasted) { 1010 | | downcasted = int56(value); 1011 | | require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); 1012 | | } 1013 | | 1014 | | /** 1015 | | * @dev Returns the downcasted int48 from int256, reverting on 1016 | | * overflow (when the input is less than smallest int48 or 1017 | | * greater than largest int48). 1018 | | * 1019 | | * Counterpart to Solidity's `int48` operator. 1020 | | * 1021 | | * Requirements: 1022 | | * 1023 | | * - input must fit into 48 bits 1024 | | * 1025 | | * _Available since v4.7._ 1026 | | */ 1027 | | function toInt48(int256 value) internal pure returns (int48 downcasted) { 1028 | | downcasted = int48(value); 1029 | | require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); 1030 | | } 1031 | | 1032 | | /** 1033 | | * @dev Returns the downcasted int40 from int256, reverting on 1034 | | * overflow (when the input is less than smallest int40 or 1035 | | * greater than largest int40). 1036 | | * 1037 | | * Counterpart to Solidity's `int40` operator. 1038 | | * 1039 | | * Requirements: 1040 | | * 1041 | | * - input must fit into 40 bits 1042 | | * 1043 | | * _Available since v4.7._ 1044 | | */ 1045 | | function toInt40(int256 value) internal pure returns (int40 downcasted) { 1046 | | downcasted = int40(value); 1047 | | require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); 1048 | | } 1049 | | 1050 | | /** 1051 | | * @dev Returns the downcasted int32 from int256, reverting on 1052 | | * overflow (when the input is less than smallest int32 or 1053 | | * greater than largest int32). 1054 | | * 1055 | | * Counterpart to Solidity's `int32` operator. 1056 | | * 1057 | | * Requirements: 1058 | | * 1059 | | * - input must fit into 32 bits 1060 | | * 1061 | | * _Available since v3.1._ 1062 | | */ 1063 | | function toInt32(int256 value) internal pure returns (int32 downcasted) { 1064 | | downcasted = int32(value); 1065 | | require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); 1066 | | } 1067 | | 1068 | | /** 1069 | | * @dev Returns the downcasted int24 from int256, reverting on 1070 | | * overflow (when the input is less than smallest int24 or 1071 | | * greater than largest int24). 1072 | | * 1073 | | * Counterpart to Solidity's `int24` operator. 1074 | | * 1075 | | * Requirements: 1076 | | * 1077 | | * - input must fit into 24 bits 1078 | | * 1079 | | * _Available since v4.7._ 1080 | | */ 1081 | | function toInt24(int256 value) internal pure returns (int24 downcasted) { 1082 | | downcasted = int24(value); 1083 | | require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); 1084 | | } 1085 | | 1086 | | /** 1087 | | * @dev Returns the downcasted int16 from int256, reverting on 1088 | | * overflow (when the input is less than smallest int16 or 1089 | | * greater than largest int16). 1090 | | * 1091 | | * Counterpart to Solidity's `int16` operator. 1092 | | * 1093 | | * Requirements: 1094 | | * 1095 | | * - input must fit into 16 bits 1096 | | * 1097 | | * _Available since v3.1._ 1098 | | */ 1099 | | function toInt16(int256 value) internal pure returns (int16 downcasted) { 1100 | | downcasted = int16(value); 1101 | | require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); 1102 | | } 1103 | | 1104 | | /** 1105 | | * @dev Returns the downcasted int8 from int256, reverting on 1106 | | * overflow (when the input is less than smallest int8 or 1107 | | * greater than largest int8). 1108 | | * 1109 | | * Counterpart to Solidity's `int8` operator. 1110 | | * 1111 | | * Requirements: 1112 | | * 1113 | | * - input must fit into 8 bits 1114 | | * 1115 | | * _Available since v3.1._ 1116 | | */ 1117 | | function toInt8(int256 value) internal pure returns (int8 downcasted) { 1118 | | downcasted = int8(value); 1119 | | require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); 1120 | | } 1121 | | 1122 | | /** 1123 | | * @dev Converts an unsigned uint256 into a signed int256. 1124 | | * 1125 | | * Requirements: 1126 | | * 1127 | | * - input must be less than or equal to maxInt256. 1128 | | * 1129 | | * _Available since v3.0._ 1130 | | */ 1131 | * | function toInt256(uint256 value) internal pure returns (int256) { 1132 | | // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive 1133 | * | require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); 1134 | * | return int256(value); 1135 | | } 1136 | | } 1137 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | // CAUTION 7 | | // This version of SafeMath should only be used with Solidity 0.8 or later, 8 | | // because it relies on the compiler's built in overflow checks. 9 | | 10 | | /** 11 | | * @dev Wrappers over Solidity's arithmetic operations. 12 | | * 13 | | * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler 14 | | * now has built in overflow checking. 15 | | */ 16 | * | library SafeMath { 17 | | /** 18 | | * @dev Returns the addition of two unsigned integers, with an overflow flag. 19 | | * 20 | | * _Available since v3.4._ 21 | | */ 22 | | function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { 23 | | unchecked { 24 | | uint256 c = a + b; 25 | | if (c < a) return (false, 0); 26 | | return (true, c); 27 | | } 28 | | } 29 | | 30 | | /** 31 | | * @dev Returns the subtraction of two unsigned integers, with an overflow flag. 32 | | * 33 | | * _Available since v3.4._ 34 | | */ 35 | | function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { 36 | | unchecked { 37 | | if (b > a) return (false, 0); 38 | | return (true, a - b); 39 | | } 40 | | } 41 | | 42 | | /** 43 | | * @dev Returns the multiplication of two unsigned integers, with an overflow flag. 44 | | * 45 | | * _Available since v3.4._ 46 | | */ 47 | | function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { 48 | | unchecked { 49 | | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 50 | | // benefit is lost if 'b' is also tested. 51 | | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 52 | | if (a == 0) return (true, 0); 53 | | uint256 c = a * b; 54 | | if (c / a != b) return (false, 0); 55 | | return (true, c); 56 | | } 57 | | } 58 | | 59 | | /** 60 | | * @dev Returns the division of two unsigned integers, with a division by zero flag. 61 | | * 62 | | * _Available since v3.4._ 63 | | */ 64 | | function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { 65 | | unchecked { 66 | | if (b == 0) return (false, 0); 67 | | return (true, a / b); 68 | | } 69 | | } 70 | | 71 | | /** 72 | | * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. 73 | | * 74 | | * _Available since v3.4._ 75 | | */ 76 | | function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { 77 | | unchecked { 78 | | if (b == 0) return (false, 0); 79 | | return (true, a % b); 80 | | } 81 | | } 82 | | 83 | | /** 84 | | * @dev Returns the addition of two unsigned integers, reverting on 85 | | * overflow. 86 | | * 87 | | * Counterpart to Solidity's `+` operator. 88 | | * 89 | | * Requirements: 90 | | * 91 | | * - Addition cannot overflow. 92 | | */ 93 | | function add(uint256 a, uint256 b) internal pure returns (uint256) { 94 | | return a + b; 95 | | } 96 | | 97 | | /** 98 | | * @dev Returns the subtraction of two unsigned integers, reverting on 99 | | * overflow (when the result is negative). 100 | | * 101 | | * Counterpart to Solidity's `-` operator. 102 | | * 103 | | * Requirements: 104 | | * 105 | | * - Subtraction cannot overflow. 106 | | */ 107 | | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 108 | | return a - b; 109 | | } 110 | | 111 | | /** 112 | | * @dev Returns the multiplication of two unsigned integers, reverting on 113 | | * overflow. 114 | | * 115 | | * Counterpart to Solidity's `*` operator. 116 | | * 117 | | * Requirements: 118 | | * 119 | | * - Multiplication cannot overflow. 120 | | */ 121 | | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 122 | | return a * b; 123 | | } 124 | | 125 | | /** 126 | | * @dev Returns the integer division of two unsigned integers, reverting on 127 | | * division by zero. The result is rounded towards zero. 128 | | * 129 | | * Counterpart to Solidity's `/` operator. 130 | | * 131 | | * Requirements: 132 | | * 133 | | * - The divisor cannot be zero. 134 | | */ 135 | | function div(uint256 a, uint256 b) internal pure returns (uint256) { 136 | | return a / b; 137 | | } 138 | | 139 | | /** 140 | | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 141 | | * reverting when dividing by zero. 142 | | * 143 | | * Counterpart to Solidity's `%` operator. This function uses a `revert` 144 | | * opcode (which leaves remaining gas untouched) while Solidity uses an 145 | | * invalid opcode to revert (consuming all remaining gas). 146 | | * 147 | | * Requirements: 148 | | * 149 | | * - The divisor cannot be zero. 150 | | */ 151 | | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 152 | | return a % b; 153 | | } 154 | | 155 | | /** 156 | | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 157 | | * overflow (when the result is negative). 158 | | * 159 | | * CAUTION: This function is deprecated because it requires allocating memory for the error 160 | | * message unnecessarily. For custom revert reasons use {trySub}. 161 | | * 162 | | * Counterpart to Solidity's `-` operator. 163 | | * 164 | | * Requirements: 165 | | * 166 | | * - Subtraction cannot overflow. 167 | | */ 168 | | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 169 | | unchecked { 170 | | require(b <= a, errorMessage); 171 | | return a - b; 172 | | } 173 | | } 174 | | 175 | | /** 176 | | * @dev Returns the integer division of two unsigned integers, reverting with custom message on 177 | | * division by zero. The result is rounded towards zero. 178 | | * 179 | | * Counterpart to Solidity's `/` operator. Note: this function uses a 180 | | * `revert` opcode (which leaves remaining gas untouched) while Solidity 181 | | * uses an invalid opcode to revert (consuming all remaining gas). 182 | | * 183 | | * Requirements: 184 | | * 185 | | * - The divisor cannot be zero. 186 | | */ 187 | | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 188 | | unchecked { 189 | | require(b > 0, errorMessage); 190 | | return a / b; 191 | | } 192 | | } 193 | | 194 | | /** 195 | | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 196 | | * reverting with custom message when dividing by zero. 197 | | * 198 | | * CAUTION: This function is deprecated because it requires allocating memory for the error 199 | | * message unnecessarily. For custom revert reasons use {tryMod}. 200 | | * 201 | | * Counterpart to Solidity's `%` operator. This function uses a `revert` 202 | | * opcode (which leaves remaining gas untouched) while Solidity uses an 203 | | * invalid opcode to revert (consuming all remaining gas). 204 | | * 205 | | * Requirements: 206 | | * 207 | | * - The divisor cannot be zero. 208 | | */ 209 | | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 210 | | unchecked { 211 | | require(b > 0, errorMessage); 212 | | return a % b; 213 | | } 214 | | } 215 | | } 216 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Standard signed math utilities missing in the Solidity language. 8 | | */ 9 | * | library SignedMath { 10 | | /** 11 | | * @dev Returns the largest of two signed numbers. 12 | | */ 13 | | function max(int256 a, int256 b) internal pure returns (int256) { 14 | | return a > b ? a : b; 15 | | } 16 | | 17 | | /** 18 | | * @dev Returns the smallest of two signed numbers. 19 | | */ 20 | | function min(int256 a, int256 b) internal pure returns (int256) { 21 | | return a < b ? a : b; 22 | | } 23 | | 24 | | /** 25 | | * @dev Returns the average of two signed numbers without overflow. 26 | | * The result is rounded towards zero. 27 | | */ 28 | | function average(int256 a, int256 b) internal pure returns (int256) { 29 | | // Formula from the book "Hacker's Delight" 30 | | int256 x = (a & b) + ((a ^ b) >> 1); 31 | | return x + (int256(uint256(x) >> 255) & (a ^ b)); 32 | | } 33 | | 34 | | /** 35 | | * @dev Returns the absolute unsigned value of a signed value. 36 | | */ 37 | * | function abs(int256 n) internal pure returns (uint256) { 38 | | unchecked { 39 | | // must be unchecked in order to support `n = type(int256).min` 40 | * | return uint256(n >= 0 ? n : -n); 41 | | } 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/math/SignedSafeMath.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol) 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @dev Wrappers over Solidity's arithmetic operations. 8 | | * 9 | | * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler 10 | | * now has built in overflow checking. 11 | | */ 12 | * | library SignedSafeMath { 13 | | /** 14 | | * @dev Returns the multiplication of two signed integers, reverting on 15 | | * overflow. 16 | | * 17 | | * Counterpart to Solidity's `*` operator. 18 | | * 19 | | * Requirements: 20 | | * 21 | | * - Multiplication cannot overflow. 22 | | */ 23 | | function mul(int256 a, int256 b) internal pure returns (int256) { 24 | | return a * b; 25 | | } 26 | | 27 | | /** 28 | | * @dev Returns the integer division of two signed integers. Reverts on 29 | | * division by zero. The result is rounded towards zero. 30 | | * 31 | | * Counterpart to Solidity's `/` operator. 32 | | * 33 | | * Requirements: 34 | | * 35 | | * - The divisor cannot be zero. 36 | | */ 37 | | function div(int256 a, int256 b) internal pure returns (int256) { 38 | | return a / b; 39 | | } 40 | | 41 | | /** 42 | | * @dev Returns the subtraction of two signed integers, reverting on 43 | | * overflow. 44 | | * 45 | | * Counterpart to Solidity's `-` operator. 46 | | * 47 | | * Requirements: 48 | | * 49 | | * - Subtraction cannot overflow. 50 | | */ 51 | | function sub(int256 a, int256 b) internal pure returns (int256) { 52 | | return a - b; 53 | | } 54 | | 55 | | /** 56 | | * @dev Returns the addition of two signed integers, reverting on 57 | | * overflow. 58 | | * 59 | | * Counterpart to Solidity's `+` operator. 60 | | * 61 | | * Requirements: 62 | | * 63 | | * - Addition cannot overflow. 64 | | */ 65 | | function add(int256 a, int256 b) internal pure returns (int256) { 66 | | return a + b; 67 | | } 68 | | } 69 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/structs/DoubleEndedQueue.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/DoubleEndedQueue.sol) 3 | | pragma solidity ^0.8.4; 4 | | 5 | | import "../math/SafeCast.sol"; 6 | | 7 | | /** 8 | | * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of 9 | | * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and 10 | | * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that 11 | | * the existing queue contents are left in storage. 12 | | * 13 | | * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be 14 | | * used in storage, and not in memory. 15 | | * ```solidity 16 | | * DoubleEndedQueue.Bytes32Deque queue; 17 | | * ``` 18 | | * 19 | | * _Available since v4.6._ 20 | | */ 21 | * | library DoubleEndedQueue { 22 | | /** 23 | | * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty. 24 | | */ 25 | | error Empty(); 26 | | 27 | | /** 28 | | * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds. 29 | | */ 30 | | error OutOfBounds(); 31 | | 32 | | /** 33 | | * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end 34 | | * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely 35 | | * assume that these 128-bit indices will not overflow, and use unchecked arithmetic. 36 | | * 37 | | * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to 38 | | * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and 39 | | * lead to unexpected behavior. 40 | | * 41 | | * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at 42 | | * data[end - 1]. 43 | | */ 44 | | struct Bytes32Deque { 45 | | int128 _begin; 46 | | int128 _end; 47 | | mapping(int128 => bytes32) _data; 48 | | } 49 | | 50 | | /** 51 | | * @dev Inserts an item at the end of the queue. 52 | | */ 53 | | function pushBack(Bytes32Deque storage deque, bytes32 value) internal { 54 | | int128 backIndex = deque._end; 55 | | deque._data[backIndex] = value; 56 | | unchecked { 57 | | deque._end = backIndex + 1; 58 | | } 59 | | } 60 | | 61 | | /** 62 | | * @dev Removes the item at the end of the queue and returns it. 63 | | * 64 | | * Reverts with `Empty` if the queue is empty. 65 | | */ 66 | | function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) { 67 | | if (empty(deque)) revert Empty(); 68 | | int128 backIndex; 69 | | unchecked { 70 | | backIndex = deque._end - 1; 71 | | } 72 | | value = deque._data[backIndex]; 73 | | delete deque._data[backIndex]; 74 | | deque._end = backIndex; 75 | | } 76 | | 77 | | /** 78 | | * @dev Inserts an item at the beginning of the queue. 79 | | */ 80 | | function pushFront(Bytes32Deque storage deque, bytes32 value) internal { 81 | | int128 frontIndex; 82 | | unchecked { 83 | | frontIndex = deque._begin - 1; 84 | | } 85 | | deque._data[frontIndex] = value; 86 | | deque._begin = frontIndex; 87 | | } 88 | | 89 | | /** 90 | | * @dev Removes the item at the beginning of the queue and returns it. 91 | | * 92 | | * Reverts with `Empty` if the queue is empty. 93 | | */ 94 | | function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) { 95 | | if (empty(deque)) revert Empty(); 96 | | int128 frontIndex = deque._begin; 97 | | value = deque._data[frontIndex]; 98 | | delete deque._data[frontIndex]; 99 | | unchecked { 100 | | deque._begin = frontIndex + 1; 101 | | } 102 | | } 103 | | 104 | | /** 105 | | * @dev Returns the item at the beginning of the queue. 106 | | * 107 | | * Reverts with `Empty` if the queue is empty. 108 | | */ 109 | | function front(Bytes32Deque storage deque) internal view returns (bytes32 value) { 110 | | if (empty(deque)) revert Empty(); 111 | | int128 frontIndex = deque._begin; 112 | | return deque._data[frontIndex]; 113 | | } 114 | | 115 | | /** 116 | | * @dev Returns the item at the end of the queue. 117 | | * 118 | | * Reverts with `Empty` if the queue is empty. 119 | | */ 120 | | function back(Bytes32Deque storage deque) internal view returns (bytes32 value) { 121 | | if (empty(deque)) revert Empty(); 122 | | int128 backIndex; 123 | | unchecked { 124 | | backIndex = deque._end - 1; 125 | | } 126 | | return deque._data[backIndex]; 127 | | } 128 | | 129 | | /** 130 | | * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at 131 | | * `length(deque) - 1`. 132 | | * 133 | | * Reverts with `OutOfBounds` if the index is out of bounds. 134 | | */ 135 | | function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) { 136 | | // int256(deque._begin) is a safe upcast 137 | | int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index)); 138 | | if (idx >= deque._end) revert OutOfBounds(); 139 | | return deque._data[idx]; 140 | | } 141 | | 142 | | /** 143 | | * @dev Resets the queue back to being empty. 144 | | * 145 | | * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses 146 | | * out on potential gas refunds. 147 | | */ 148 | | function clear(Bytes32Deque storage deque) internal { 149 | | deque._begin = 0; 150 | | deque._end = 0; 151 | | } 152 | | 153 | | /** 154 | | * @dev Returns the number of items in the queue. 155 | | */ 156 | | function length(Bytes32Deque storage deque) internal view returns (uint256) { 157 | | // The interface preserves the invariant that begin <= end so we assume this will not overflow. 158 | | // We also assume there are at most int256.max items in the queue. 159 | | unchecked { 160 | | return uint256(int256(deque._end) - int256(deque._begin)); 161 | | } 162 | | } 163 | | 164 | | /** 165 | | * @dev Returns true if the queue is empty. 166 | | */ 167 | | function empty(Bytes32Deque storage deque) internal view returns (bool) { 168 | | return deque._end <= deque._begin; 169 | | } 170 | | } 171 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/@openzeppelin/contracts/utils/structs/EnumerableSet.sol 1 | | // SPDX-License-Identifier: MIT 2 | | // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) 3 | | // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. 4 | | 5 | | pragma solidity ^0.8.0; 6 | | 7 | | /** 8 | | * @dev Library for managing 9 | | * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive 10 | | * types. 11 | | * 12 | | * Sets have the following properties: 13 | | * 14 | | * - Elements are added, removed, and checked for existence in constant time 15 | | * (O(1)). 16 | | * - Elements are enumerated in O(n). No guarantees are made on the ordering. 17 | | * 18 | | * ```solidity 19 | | * contract Example { 20 | | * // Add the library methods 21 | | * using EnumerableSet for EnumerableSet.AddressSet; 22 | | * 23 | | * // Declare a set state variable 24 | | * EnumerableSet.AddressSet private mySet; 25 | | * } 26 | | * ``` 27 | | * 28 | | * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) 29 | | * and `uint256` (`UintSet`) are supported. 30 | | * 31 | | * [WARNING] 32 | | * ==== 33 | | * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure 34 | | * unusable. 35 | | * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. 36 | | * 37 | | * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an 38 | | * array of EnumerableSet. 39 | | * ==== 40 | | */ 41 | * | library EnumerableSet { 42 | | // To implement this library for multiple types with as little code 43 | | // repetition as possible, we write it in terms of a generic Set type with 44 | | // bytes32 values. 45 | | // The Set implementation uses private functions, and user-facing 46 | | // implementations (such as AddressSet) are just wrappers around the 47 | | // underlying Set. 48 | | // This means that we can only create new EnumerableSets for types that fit 49 | | // in bytes32. 50 | | 51 | | struct Set { 52 | | // Storage of set values 53 | | bytes32[] _values; 54 | | // Position of the value in the `values` array, plus 1 because index 0 55 | | // means a value is not in the set. 56 | | mapping(bytes32 => uint256) _indexes; 57 | | } 58 | | 59 | | /** 60 | | * @dev Add a value to a set. O(1). 61 | | * 62 | | * Returns true if the value was added to the set, that is if it was not 63 | | * already present. 64 | | */ 65 | * | function _add(Set storage set, bytes32 value) private returns (bool) { 66 | * | if (!_contains(set, value)) { 67 | * | set._values.push(value); 68 | | // The value is stored at length-1, but we add 1 to all indexes 69 | | // and use 0 as a sentinel value 70 | * | set._indexes[value] = set._values.length; 71 | * | return true; 72 | | } else { 73 | * | return false; 74 | | } 75 | | } 76 | | 77 | | /** 78 | | * @dev Removes a value from a set. O(1). 79 | | * 80 | | * Returns true if the value was removed from the set, that is if it was 81 | | * present. 82 | | */ 83 | * | function _remove(Set storage set, bytes32 value) private returns (bool) { 84 | | // We read and store the value's index to prevent multiple reads from the same storage slot 85 | * | uint256 valueIndex = set._indexes[value]; 86 | | 87 | * | if (valueIndex != 0) { 88 | | // Equivalent to contains(set, value) 89 | | // To delete an element from the _values array in O(1), we swap the element to delete with the last one in 90 | | // the array, and then remove the last element (sometimes called as 'swap and pop'). 91 | | // This modifies the order of the array, as noted in {at}. 92 | | 93 | * | uint256 toDeleteIndex = valueIndex - 1; 94 | * | uint256 lastIndex = set._values.length - 1; 95 | | 96 | * | if (lastIndex != toDeleteIndex) { 97 | * | bytes32 lastValue = set._values[lastIndex]; 98 | | 99 | | // Move the last value to the index where the value to delete is 100 | * | set._values[toDeleteIndex] = lastValue; 101 | | // Update the index for the moved value 102 | * | set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex 103 | | } 104 | | 105 | | // Delete the slot where the moved value was stored 106 | * | set._values.pop(); 107 | | 108 | | // Delete the index for the deleted slot 109 | * | delete set._indexes[value]; 110 | | 111 | * | return true; 112 | | } else { 113 | | return false; 114 | | } 115 | | } 116 | | 117 | | /** 118 | | * @dev Returns true if the value is in the set. O(1). 119 | | */ 120 | * | function _contains(Set storage set, bytes32 value) private view returns (bool) { 121 | * | return set._indexes[value] != 0; 122 | | } 123 | | 124 | | /** 125 | | * @dev Returns the number of values on the set. O(1). 126 | | */ 127 | * | function _length(Set storage set) private view returns (uint256) { 128 | * | return set._values.length; 129 | | } 130 | | 131 | | /** 132 | | * @dev Returns the value stored at position `index` in the set. O(1). 133 | | * 134 | | * Note that there are no guarantees on the ordering of values inside the 135 | | * array, and it may change when more values are added or removed. 136 | | * 137 | | * Requirements: 138 | | * 139 | | * - `index` must be strictly less than {length}. 140 | | */ 141 | * | function _at(Set storage set, uint256 index) private view returns (bytes32) { 142 | * | return set._values[index]; 143 | | } 144 | | 145 | | /** 146 | | * @dev Return the entire set in an array 147 | | * 148 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed 149 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that 150 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function 151 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. 152 | | */ 153 | | function _values(Set storage set) private view returns (bytes32[] memory) { 154 | | return set._values; 155 | | } 156 | | 157 | | // Bytes32Set 158 | | 159 | | struct Bytes32Set { 160 | | Set _inner; 161 | | } 162 | | 163 | | /** 164 | | * @dev Add a value to a set. O(1). 165 | | * 166 | | * Returns true if the value was added to the set, that is if it was not 167 | | * already present. 168 | | */ 169 | * | function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { 170 | * | return _add(set._inner, value); 171 | | } 172 | | 173 | | /** 174 | | * @dev Removes a value from a set. O(1). 175 | | * 176 | | * Returns true if the value was removed from the set, that is if it was 177 | | * present. 178 | | */ 179 | * | function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { 180 | * | return _remove(set._inner, value); 181 | | } 182 | | 183 | | /** 184 | | * @dev Returns true if the value is in the set. O(1). 185 | | */ 186 | * | function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { 187 | * | return _contains(set._inner, value); 188 | | } 189 | | 190 | | /** 191 | | * @dev Returns the number of values in the set. O(1). 192 | | */ 193 | * | function length(Bytes32Set storage set) internal view returns (uint256) { 194 | * | return _length(set._inner); 195 | | } 196 | | 197 | | /** 198 | | * @dev Returns the value stored at position `index` in the set. O(1). 199 | | * 200 | | * Note that there are no guarantees on the ordering of values inside the 201 | | * array, and it may change when more values are added or removed. 202 | | * 203 | | * Requirements: 204 | | * 205 | | * - `index` must be strictly less than {length}. 206 | | */ 207 | * | function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { 208 | * | return _at(set._inner, index); 209 | | } 210 | | 211 | | /** 212 | | * @dev Return the entire set in an array 213 | | * 214 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed 215 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that 216 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function 217 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. 218 | | */ 219 | | function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { 220 | | bytes32[] memory store = _values(set._inner); 221 | | bytes32[] memory result; 222 | | 223 | | /// @solidity memory-safe-assembly 224 | | assembly { 225 | | result := store 226 | | } 227 | | 228 | | return result; 229 | | } 230 | | 231 | | // AddressSet 232 | | 233 | | struct AddressSet { 234 | | Set _inner; 235 | | } 236 | | 237 | | /** 238 | | * @dev Add a value to a set. O(1). 239 | | * 240 | | * Returns true if the value was added to the set, that is if it was not 241 | | * already present. 242 | | */ 243 | * | function add(AddressSet storage set, address value) internal returns (bool) { 244 | * | return _add(set._inner, bytes32(uint256(uint160(value)))); 245 | | } 246 | | 247 | | /** 248 | | * @dev Removes a value from a set. O(1). 249 | | * 250 | | * Returns true if the value was removed from the set, that is if it was 251 | | * present. 252 | | */ 253 | * | function remove(AddressSet storage set, address value) internal returns (bool) { 254 | * | return _remove(set._inner, bytes32(uint256(uint160(value)))); 255 | | } 256 | | 257 | | /** 258 | | * @dev Returns true if the value is in the set. O(1). 259 | | */ 260 | * | function contains(AddressSet storage set, address value) internal view returns (bool) { 261 | * | return _contains(set._inner, bytes32(uint256(uint160(value)))); 262 | | } 263 | | 264 | | /** 265 | | * @dev Returns the number of values in the set. O(1). 266 | | */ 267 | * | function length(AddressSet storage set) internal view returns (uint256) { 268 | * | return _length(set._inner); 269 | | } 270 | | 271 | | /** 272 | | * @dev Returns the value stored at position `index` in the set. O(1). 273 | | * 274 | | * Note that there are no guarantees on the ordering of values inside the 275 | | * array, and it may change when more values are added or removed. 276 | | * 277 | | * Requirements: 278 | | * 279 | | * - `index` must be strictly less than {length}. 280 | | */ 281 | * | function at(AddressSet storage set, uint256 index) internal view returns (address) { 282 | * | return address(uint160(uint256(_at(set._inner, index)))); 283 | | } 284 | | 285 | | /** 286 | | * @dev Return the entire set in an array 287 | | * 288 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed 289 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that 290 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function 291 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. 292 | | */ 293 | | function values(AddressSet storage set) internal view returns (address[] memory) { 294 | | bytes32[] memory store = _values(set._inner); 295 | | address[] memory result; 296 | | 297 | | /// @solidity memory-safe-assembly 298 | | assembly { 299 | | result := store 300 | | } 301 | | 302 | | return result; 303 | | } 304 | | 305 | | // UintSet 306 | | 307 | | struct UintSet { 308 | | Set _inner; 309 | | } 310 | | 311 | | /** 312 | | * @dev Add a value to a set. O(1). 313 | | * 314 | | * Returns true if the value was added to the set, that is if it was not 315 | | * already present. 316 | | */ 317 | * | function add(UintSet storage set, uint256 value) internal returns (bool) { 318 | * | return _add(set._inner, bytes32(value)); 319 | | } 320 | | 321 | | /** 322 | | * @dev Removes a value from a set. O(1). 323 | | * 324 | | * Returns true if the value was removed from the set, that is if it was 325 | | * present. 326 | | */ 327 | * | function remove(UintSet storage set, uint256 value) internal returns (bool) { 328 | * | return _remove(set._inner, bytes32(value)); 329 | | } 330 | | 331 | | /** 332 | | * @dev Returns true if the value is in the set. O(1). 333 | | */ 334 | * | function contains(UintSet storage set, uint256 value) internal view returns (bool) { 335 | * | return _contains(set._inner, bytes32(value)); 336 | | } 337 | | 338 | | /** 339 | | * @dev Returns the number of values in the set. O(1). 340 | | */ 341 | * | function length(UintSet storage set) internal view returns (uint256) { 342 | * | return _length(set._inner); 343 | | } 344 | | 345 | | /** 346 | | * @dev Returns the value stored at position `index` in the set. O(1). 347 | | * 348 | | * Note that there are no guarantees on the ordering of values inside the 349 | | * array, and it may change when more values are added or removed. 350 | | * 351 | | * Requirements: 352 | | * 353 | | * - `index` must be strictly less than {length}. 354 | | */ 355 | * | function at(UintSet storage set, uint256 index) internal view returns (uint256) { 356 | * | return uint256(_at(set._inner, index)); 357 | | } 358 | | 359 | | /** 360 | | * @dev Return the entire set in an array 361 | | * 362 | | * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed 363 | | * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that 364 | | * this function has an unbounded cost, and using it as part of a state-changing function may render the function 365 | | * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. 366 | | */ 367 | | function values(UintSet storage set) internal view returns (uint256[] memory) { 368 | | bytes32[] memory store = _values(set._inner); 369 | | uint256[] memory result; 370 | | 371 | | /// @solidity memory-safe-assembly 372 | | assembly { 373 | | result := store 374 | | } 375 | | 376 | | return result; 377 | | } 378 | | } 379 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/prb-math/contracts/PRBMath.sol 1 | | // SPDX-License-Identifier: Unlicense 2 | | pragma solidity >=0.8.4; 3 | | 4 | | /// @notice Emitted when the result overflows uint256. 5 | | error PRBMath__MulDivFixedPointOverflow(uint256 prod1); 6 | | 7 | | /// @notice Emitted when the result overflows uint256. 8 | | error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator); 9 | | 10 | | /// @notice Emitted when one of the inputs is type(int256).min. 11 | | error PRBMath__MulDivSignedInputTooSmall(); 12 | | 13 | | /// @notice Emitted when the intermediary absolute result overflows int256. 14 | | error PRBMath__MulDivSignedOverflow(uint256 rAbs); 15 | | 16 | | /// @notice Emitted when the input is MIN_SD59x18. 17 | | error PRBMathSD59x18__AbsInputTooSmall(); 18 | | 19 | | /// @notice Emitted when ceiling a number overflows SD59x18. 20 | | error PRBMathSD59x18__CeilOverflow(int256 x); 21 | | 22 | | /// @notice Emitted when one of the inputs is MIN_SD59x18. 23 | | error PRBMathSD59x18__DivInputTooSmall(); 24 | | 25 | | /// @notice Emitted when one of the intermediary unsigned results overflows SD59x18. 26 | | error PRBMathSD59x18__DivOverflow(uint256 rAbs); 27 | | 28 | | /// @notice Emitted when the input is greater than 133.084258667509499441. 29 | | error PRBMathSD59x18__ExpInputTooBig(int256 x); 30 | | 31 | | /// @notice Emitted when the input is greater than 192. 32 | | error PRBMathSD59x18__Exp2InputTooBig(int256 x); 33 | | 34 | | /// @notice Emitted when flooring a number underflows SD59x18. 35 | | error PRBMathSD59x18__FloorUnderflow(int256 x); 36 | | 37 | | /// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18. 38 | | error PRBMathSD59x18__FromIntOverflow(int256 x); 39 | | 40 | | /// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18. 41 | | error PRBMathSD59x18__FromIntUnderflow(int256 x); 42 | | 43 | | /// @notice Emitted when the product of the inputs is negative. 44 | | error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y); 45 | | 46 | | /// @notice Emitted when multiplying the inputs overflows SD59x18. 47 | | error PRBMathSD59x18__GmOverflow(int256 x, int256 y); 48 | | 49 | | /// @notice Emitted when the input is less than or equal to zero. 50 | | error PRBMathSD59x18__LogInputTooSmall(int256 x); 51 | | 52 | | /// @notice Emitted when one of the inputs is MIN_SD59x18. 53 | | error PRBMathSD59x18__MulInputTooSmall(); 54 | | 55 | | /// @notice Emitted when the intermediary absolute result overflows SD59x18. 56 | | error PRBMathSD59x18__MulOverflow(uint256 rAbs); 57 | | 58 | | /// @notice Emitted when the intermediary absolute result overflows SD59x18. 59 | | error PRBMathSD59x18__PowuOverflow(uint256 rAbs); 60 | | 61 | | /// @notice Emitted when the input is negative. 62 | | error PRBMathSD59x18__SqrtNegativeInput(int256 x); 63 | | 64 | | /// @notice Emitted when the calculating the square root overflows SD59x18. 65 | | error PRBMathSD59x18__SqrtOverflow(int256 x); 66 | | 67 | | /// @notice Emitted when addition overflows UD60x18. 68 | | error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y); 69 | | 70 | | /// @notice Emitted when ceiling a number overflows UD60x18. 71 | | error PRBMathUD60x18__CeilOverflow(uint256 x); 72 | | 73 | | /// @notice Emitted when the input is greater than 133.084258667509499441. 74 | | error PRBMathUD60x18__ExpInputTooBig(uint256 x); 75 | | 76 | | /// @notice Emitted when the input is greater than 192. 77 | | error PRBMathUD60x18__Exp2InputTooBig(uint256 x); 78 | | 79 | | /// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18. 80 | | error PRBMathUD60x18__FromUintOverflow(uint256 x); 81 | | 82 | | /// @notice Emitted when multiplying the inputs overflows UD60x18. 83 | | error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y); 84 | | 85 | | /// @notice Emitted when the input is less than 1. 86 | | error PRBMathUD60x18__LogInputTooSmall(uint256 x); 87 | | 88 | | /// @notice Emitted when the calculating the square root overflows UD60x18. 89 | | error PRBMathUD60x18__SqrtOverflow(uint256 x); 90 | | 91 | | /// @notice Emitted when subtraction underflows UD60x18. 92 | | error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y); 93 | | 94 | | /// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library 95 | | /// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point 96 | | /// representation. When it does not, it is explicitly mentioned in the NatSpec documentation. 97 | * | library PRBMath { 98 | | /// STRUCTS /// 99 | | 100 | | struct SD59x18 { 101 | | int256 value; 102 | | } 103 | | 104 | | struct UD60x18 { 105 | | uint256 value; 106 | | } 107 | | 108 | | /// STORAGE /// 109 | | 110 | | /// @dev How many trailing decimals can be represented. 111 | * | uint256 internal constant SCALE = 1e18; 112 | | 113 | | /// @dev Largest power of two divisor of SCALE. 114 | | uint256 internal constant SCALE_LPOTD = 262144; 115 | | 116 | | /// @dev SCALE inverted mod 2^256. 117 | | uint256 internal constant SCALE_INVERSE = 118 | | 78156646155174841979727994598816262306175212592076161876661_508869554232690281; 119 | | 120 | | /// FUNCTIONS /// 121 | | 122 | | /// @notice Calculates the binary exponent of x using the binary fraction method. 123 | | /// @dev Has to use 192.64-bit fixed-point numbers. 124 | | /// See https://ethereum.stackexchange.com/a/96594/24693. 125 | | /// @param x The exponent as an unsigned 192.64-bit fixed-point number. 126 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 127 | * | function exp2(uint256 x) internal pure returns (uint256 result) { 128 | | unchecked { 129 | | // Start from 0.5 in the 192.64-bit fixed-point format. 130 | * | result = 0x800000000000000000000000000000000000000000000000; 131 | | 132 | | // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows 133 | | // because the initial result is 2^191 and all magic factors are less than 2^65. 134 | * | if (x & 0x8000000000000000 > 0) { 135 | | result = (result * 0x16A09E667F3BCC909) >> 64; 136 | | } 137 | * | if (x & 0x4000000000000000 > 0) { 138 | | result = (result * 0x1306FE0A31B7152DF) >> 64; 139 | | } 140 | * | if (x & 0x2000000000000000 > 0) { 141 | | result = (result * 0x1172B83C7D517ADCE) >> 64; 142 | | } 143 | * | if (x & 0x1000000000000000 > 0) { 144 | | result = (result * 0x10B5586CF9890F62A) >> 64; 145 | | } 146 | * | if (x & 0x800000000000000 > 0) { 147 | | result = (result * 0x1059B0D31585743AE) >> 64; 148 | | } 149 | * | if (x & 0x400000000000000 > 0) { 150 | | result = (result * 0x102C9A3E778060EE7) >> 64; 151 | | } 152 | * | if (x & 0x200000000000000 > 0) { 153 | | result = (result * 0x10163DA9FB33356D8) >> 64; 154 | | } 155 | * | if (x & 0x100000000000000 > 0) { 156 | | result = (result * 0x100B1AFA5ABCBED61) >> 64; 157 | | } 158 | * | if (x & 0x80000000000000 > 0) { 159 | | result = (result * 0x10058C86DA1C09EA2) >> 64; 160 | | } 161 | * | if (x & 0x40000000000000 > 0) { 162 | | result = (result * 0x1002C605E2E8CEC50) >> 64; 163 | | } 164 | * | if (x & 0x20000000000000 > 0) { 165 | | result = (result * 0x100162F3904051FA1) >> 64; 166 | | } 167 | * | if (x & 0x10000000000000 > 0) { 168 | | result = (result * 0x1000B175EFFDC76BA) >> 64; 169 | | } 170 | * | if (x & 0x8000000000000 > 0) { 171 | | result = (result * 0x100058BA01FB9F96D) >> 64; 172 | | } 173 | * | if (x & 0x4000000000000 > 0) { 174 | | result = (result * 0x10002C5CC37DA9492) >> 64; 175 | | } 176 | * | if (x & 0x2000000000000 > 0) { 177 | | result = (result * 0x1000162E525EE0547) >> 64; 178 | | } 179 | * | if (x & 0x1000000000000 > 0) { 180 | | result = (result * 0x10000B17255775C04) >> 64; 181 | | } 182 | * | if (x & 0x800000000000 > 0) { 183 | | result = (result * 0x1000058B91B5BC9AE) >> 64; 184 | | } 185 | * | if (x & 0x400000000000 > 0) { 186 | | result = (result * 0x100002C5C89D5EC6D) >> 64; 187 | | } 188 | * | if (x & 0x200000000000 > 0) { 189 | | result = (result * 0x10000162E43F4F831) >> 64; 190 | | } 191 | * | if (x & 0x100000000000 > 0) { 192 | | result = (result * 0x100000B1721BCFC9A) >> 64; 193 | | } 194 | * | if (x & 0x80000000000 > 0) { 195 | | result = (result * 0x10000058B90CF1E6E) >> 64; 196 | | } 197 | * | if (x & 0x40000000000 > 0) { 198 | | result = (result * 0x1000002C5C863B73F) >> 64; 199 | | } 200 | * | if (x & 0x20000000000 > 0) { 201 | | result = (result * 0x100000162E430E5A2) >> 64; 202 | | } 203 | * | if (x & 0x10000000000 > 0) { 204 | | result = (result * 0x1000000B172183551) >> 64; 205 | | } 206 | * | if (x & 0x8000000000 > 0) { 207 | | result = (result * 0x100000058B90C0B49) >> 64; 208 | | } 209 | * | if (x & 0x4000000000 > 0) { 210 | | result = (result * 0x10000002C5C8601CC) >> 64; 211 | | } 212 | * | if (x & 0x2000000000 > 0) { 213 | | result = (result * 0x1000000162E42FFF0) >> 64; 214 | | } 215 | * | if (x & 0x1000000000 > 0) { 216 | | result = (result * 0x10000000B17217FBB) >> 64; 217 | | } 218 | * | if (x & 0x800000000 > 0) { 219 | | result = (result * 0x1000000058B90BFCE) >> 64; 220 | | } 221 | * | if (x & 0x400000000 > 0) { 222 | | result = (result * 0x100000002C5C85FE3) >> 64; 223 | | } 224 | * | if (x & 0x200000000 > 0) { 225 | | result = (result * 0x10000000162E42FF1) >> 64; 226 | | } 227 | * | if (x & 0x100000000 > 0) { 228 | | result = (result * 0x100000000B17217F8) >> 64; 229 | | } 230 | * | if (x & 0x80000000 > 0) { 231 | | result = (result * 0x10000000058B90BFC) >> 64; 232 | | } 233 | * | if (x & 0x40000000 > 0) { 234 | | result = (result * 0x1000000002C5C85FE) >> 64; 235 | | } 236 | * | if (x & 0x20000000 > 0) { 237 | | result = (result * 0x100000000162E42FF) >> 64; 238 | | } 239 | * | if (x & 0x10000000 > 0) { 240 | | result = (result * 0x1000000000B17217F) >> 64; 241 | | } 242 | * | if (x & 0x8000000 > 0) { 243 | | result = (result * 0x100000000058B90C0) >> 64; 244 | | } 245 | * | if (x & 0x4000000 > 0) { 246 | | result = (result * 0x10000000002C5C860) >> 64; 247 | | } 248 | * | if (x & 0x2000000 > 0) { 249 | | result = (result * 0x1000000000162E430) >> 64; 250 | | } 251 | * | if (x & 0x1000000 > 0) { 252 | | result = (result * 0x10000000000B17218) >> 64; 253 | | } 254 | * | if (x & 0x800000 > 0) { 255 | | result = (result * 0x1000000000058B90C) >> 64; 256 | | } 257 | * | if (x & 0x400000 > 0) { 258 | | result = (result * 0x100000000002C5C86) >> 64; 259 | | } 260 | * | if (x & 0x200000 > 0) { 261 | | result = (result * 0x10000000000162E43) >> 64; 262 | | } 263 | * | if (x & 0x100000 > 0) { 264 | | result = (result * 0x100000000000B1721) >> 64; 265 | | } 266 | * | if (x & 0x80000 > 0) { 267 | | result = (result * 0x10000000000058B91) >> 64; 268 | | } 269 | * | if (x & 0x40000 > 0) { 270 | | result = (result * 0x1000000000002C5C8) >> 64; 271 | | } 272 | * | if (x & 0x20000 > 0) { 273 | | result = (result * 0x100000000000162E4) >> 64; 274 | | } 275 | * | if (x & 0x10000 > 0) { 276 | | result = (result * 0x1000000000000B172) >> 64; 277 | | } 278 | * | if (x & 0x8000 > 0) { 279 | | result = (result * 0x100000000000058B9) >> 64; 280 | | } 281 | * | if (x & 0x4000 > 0) { 282 | | result = (result * 0x10000000000002C5D) >> 64; 283 | | } 284 | * | if (x & 0x2000 > 0) { 285 | | result = (result * 0x1000000000000162E) >> 64; 286 | | } 287 | * | if (x & 0x1000 > 0) { 288 | | result = (result * 0x10000000000000B17) >> 64; 289 | | } 290 | * | if (x & 0x800 > 0) { 291 | | result = (result * 0x1000000000000058C) >> 64; 292 | | } 293 | * | if (x & 0x400 > 0) { 294 | | result = (result * 0x100000000000002C6) >> 64; 295 | | } 296 | * | if (x & 0x200 > 0) { 297 | | result = (result * 0x10000000000000163) >> 64; 298 | | } 299 | * | if (x & 0x100 > 0) { 300 | | result = (result * 0x100000000000000B1) >> 64; 301 | | } 302 | * | if (x & 0x80 > 0) { 303 | | result = (result * 0x10000000000000059) >> 64; 304 | | } 305 | * | if (x & 0x40 > 0) { 306 | | result = (result * 0x1000000000000002C) >> 64; 307 | | } 308 | * | if (x & 0x20 > 0) { 309 | | result = (result * 0x10000000000000016) >> 64; 310 | | } 311 | * | if (x & 0x10 > 0) { 312 | | result = (result * 0x1000000000000000B) >> 64; 313 | | } 314 | * | if (x & 0x8 > 0) { 315 | | result = (result * 0x10000000000000006) >> 64; 316 | | } 317 | * | if (x & 0x4 > 0) { 318 | | result = (result * 0x10000000000000003) >> 64; 319 | | } 320 | * | if (x & 0x2 > 0) { 321 | | result = (result * 0x10000000000000001) >> 64; 322 | | } 323 | * | if (x & 0x1 > 0) { 324 | | result = (result * 0x10000000000000001) >> 64; 325 | | } 326 | | 327 | | // We're doing two things at the same time: 328 | | // 329 | | // 1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for 330 | | // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191 331 | | // rather than 192. 332 | | // 2. Convert the result to the unsigned 60.18-decimal fixed-point format. 333 | | // 334 | | // This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n". 335 | * | result *= SCALE; 336 | * | result >>= (191 - (x >> 64)); 337 | | } 338 | | } 339 | | 340 | | /// @notice Finds the zero-based index of the first one in the binary representation of x. 341 | | /// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set 342 | | /// @param x The uint256 number for which to find the index of the most significant bit. 343 | | /// @return msb The index of the most significant bit as an uint256. 344 | * | function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) { 345 | * | if (x >= 2**128) { 346 | | x >>= 128; 347 | | msb += 128; 348 | | } 349 | * | if (x >= 2**64) { 350 | | x >>= 64; 351 | | msb += 64; 352 | | } 353 | * | if (x >= 2**32) { 354 | * | x >>= 32; 355 | * | msb += 32; 356 | | } 357 | * | if (x >= 2**16) { 358 | * | x >>= 16; 359 | * | msb += 16; 360 | | } 361 | * | if (x >= 2**8) { 362 | * | x >>= 8; 363 | * | msb += 8; 364 | | } 365 | * | if (x >= 2**4) { 366 | * | x >>= 4; 367 | * | msb += 4; 368 | | } 369 | * | if (x >= 2**2) { 370 | * | x >>= 2; 371 | * | msb += 2; 372 | | } 373 | * | if (x >= 2**1) { 374 | | // No need to shift x any more. 375 | * | msb += 1; 376 | | } 377 | | } 378 | | 379 | | /// @notice Calculates floor(x*y÷denominator) with full precision. 380 | | /// 381 | | /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv. 382 | | /// 383 | | /// Requirements: 384 | | /// - The denominator cannot be zero. 385 | | /// - The result must fit within uint256. 386 | | /// 387 | | /// Caveats: 388 | | /// - This function does not work with fixed-point numbers. 389 | | /// 390 | | /// @param x The multiplicand as an uint256. 391 | | /// @param y The multiplier as an uint256. 392 | | /// @param denominator The divisor as an uint256. 393 | | /// @return result The result as an uint256. 394 | | function mulDiv( 395 | | uint256 x, 396 | | uint256 y, 397 | | uint256 denominator 398 | | ) internal pure returns (uint256 result) { 399 | | // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use 400 | | // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 401 | | // variables such that product = prod1 * 2^256 + prod0. 402 | | uint256 prod0; // Least significant 256 bits of the product 403 | | uint256 prod1; // Most significant 256 bits of the product 404 | | assembly { 405 | | let mm := mulmod(x, y, not(0)) 406 | | prod0 := mul(x, y) 407 | | prod1 := sub(sub(mm, prod0), lt(mm, prod0)) 408 | | } 409 | | 410 | | // Handle non-overflow cases, 256 by 256 division. 411 | | if (prod1 == 0) { 412 | | unchecked { 413 | | result = prod0 / denominator; 414 | | } 415 | | return result; 416 | | } 417 | | 418 | | // Make sure the result is less than 2^256. Also prevents denominator == 0. 419 | | if (prod1 >= denominator) { 420 | | revert PRBMath__MulDivOverflow(prod1, denominator); 421 | | } 422 | | 423 | | /////////////////////////////////////////////// 424 | | // 512 by 256 division. 425 | | /////////////////////////////////////////////// 426 | | 427 | | // Make division exact by subtracting the remainder from [prod1 prod0]. 428 | | uint256 remainder; 429 | | assembly { 430 | | // Compute remainder using mulmod. 431 | | remainder := mulmod(x, y, denominator) 432 | | 433 | | // Subtract 256 bit number from 512 bit number. 434 | | prod1 := sub(prod1, gt(remainder, prod0)) 435 | | prod0 := sub(prod0, remainder) 436 | | } 437 | | 438 | | // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. 439 | | // See https://cs.stackexchange.com/q/138556/92363. 440 | | unchecked { 441 | | // Does not overflow because the denominator cannot be zero at this stage in the function. 442 | | uint256 lpotdod = denominator & (~denominator + 1); 443 | | assembly { 444 | | // Divide denominator by lpotdod. 445 | | denominator := div(denominator, lpotdod) 446 | | 447 | | // Divide [prod1 prod0] by lpotdod. 448 | | prod0 := div(prod0, lpotdod) 449 | | 450 | | // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one. 451 | | lpotdod := add(div(sub(0, lpotdod), lpotdod), 1) 452 | | } 453 | | 454 | | // Shift in bits from prod1 into prod0. 455 | | prod0 |= prod1 * lpotdod; 456 | | 457 | | // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such 458 | | // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for 459 | | // four bits. That is, denominator * inv = 1 mod 2^4. 460 | | uint256 inverse = (3 * denominator) ^ 2; 461 | | 462 | | // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works 463 | | // in modular arithmetic, doubling the correct bits in each step. 464 | | inverse *= 2 - denominator * inverse; // inverse mod 2^8 465 | | inverse *= 2 - denominator * inverse; // inverse mod 2^16 466 | | inverse *= 2 - denominator * inverse; // inverse mod 2^32 467 | | inverse *= 2 - denominator * inverse; // inverse mod 2^64 468 | | inverse *= 2 - denominator * inverse; // inverse mod 2^128 469 | | inverse *= 2 - denominator * inverse; // inverse mod 2^256 470 | | 471 | | // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. 472 | | // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is 473 | | // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 474 | | // is no longer required. 475 | | result = prod0 * inverse; 476 | | return result; 477 | | } 478 | | } 479 | | 480 | | /// @notice Calculates floor(x*y÷1e18) with full precision. 481 | | /// 482 | | /// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the 483 | | /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of 484 | | /// being rounded to 1e-18. See "Listing 6" and text above it at https://accu.org/index.php/journals/1717. 485 | | /// 486 | | /// Requirements: 487 | | /// - The result must fit within uint256. 488 | | /// 489 | | /// Caveats: 490 | | /// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works. 491 | | /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations: 492 | | /// 1. x * y = type(uint256).max * SCALE 493 | | /// 2. (x * y) % SCALE >= SCALE / 2 494 | | /// 495 | | /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. 496 | | /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. 497 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 498 | * | function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) { 499 | * | uint256 prod0; 500 | * | uint256 prod1; 501 | * | assembly { 502 | * | let mm := mulmod(x, y, not(0)) 503 | * | prod0 := mul(x, y) 504 | * | prod1 := sub(sub(mm, prod0), lt(mm, prod0)) 505 | | } 506 | | 507 | * | if (prod1 >= SCALE) { 508 | | revert PRBMath__MulDivFixedPointOverflow(prod1); 509 | | } 510 | | 511 | * | uint256 remainder; 512 | * | uint256 roundUpUnit; 513 | | assembly { 514 | * | remainder := mulmod(x, y, SCALE) 515 | * | roundUpUnit := gt(remainder, 499999999999999999) 516 | | } 517 | | 518 | * | if (prod1 == 0) { 519 | | unchecked { 520 | * | result = (prod0 / SCALE) + roundUpUnit; 521 | * | return result; 522 | | } 523 | | } 524 | | 525 | | assembly { 526 | | result := add( 527 | | mul( 528 | | or( 529 | | div(sub(prod0, remainder), SCALE_LPOTD), 530 | | mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1)) 531 | | ), 532 | | SCALE_INVERSE 533 | | ), 534 | | roundUpUnit 535 | | ) 536 | | } 537 | | } 538 | | 539 | | /// @notice Calculates floor(x*y÷denominator) with full precision. 540 | | /// 541 | | /// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately. 542 | | /// 543 | | /// Requirements: 544 | | /// - None of the inputs can be type(int256).min. 545 | | /// - The result must fit within int256. 546 | | /// 547 | | /// @param x The multiplicand as an int256. 548 | | /// @param y The multiplier as an int256. 549 | | /// @param denominator The divisor as an int256. 550 | | /// @return result The result as an int256. 551 | | function mulDivSigned( 552 | | int256 x, 553 | | int256 y, 554 | | int256 denominator 555 | | ) internal pure returns (int256 result) { 556 | | if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) { 557 | | revert PRBMath__MulDivSignedInputTooSmall(); 558 | | } 559 | | 560 | | // Get hold of the absolute values of x, y and the denominator. 561 | | uint256 ax; 562 | | uint256 ay; 563 | | uint256 ad; 564 | | unchecked { 565 | | ax = x < 0 ? uint256(-x) : uint256(x); 566 | | ay = y < 0 ? uint256(-y) : uint256(y); 567 | | ad = denominator < 0 ? uint256(-denominator) : uint256(denominator); 568 | | } 569 | | 570 | | // Compute the absolute value of (x*y)÷denominator. The result must fit within int256. 571 | | uint256 rAbs = mulDiv(ax, ay, ad); 572 | | if (rAbs > uint256(type(int256).max)) { 573 | | revert PRBMath__MulDivSignedOverflow(rAbs); 574 | | } 575 | | 576 | | // Get the signs of x, y and the denominator. 577 | | uint256 sx; 578 | | uint256 sy; 579 | | uint256 sd; 580 | | assembly { 581 | | sx := sgt(x, sub(0, 1)) 582 | | sy := sgt(y, sub(0, 1)) 583 | | sd := sgt(denominator, sub(0, 1)) 584 | | } 585 | | 586 | | // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs. 587 | | // If yes, the result should be negative. 588 | | result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs); 589 | | } 590 | | 591 | | /// @notice Calculates the square root of x, rounding down. 592 | | /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. 593 | | /// 594 | | /// Caveats: 595 | | /// - This function does not work with fixed-point numbers. 596 | | /// 597 | | /// @param x The uint256 number for which to calculate the square root. 598 | | /// @return result The result as an uint256. 599 | | function sqrt(uint256 x) internal pure returns (uint256 result) { 600 | | if (x == 0) { 601 | | return 0; 602 | | } 603 | | 604 | | // Set the initial guess to the least power of two that is greater than or equal to sqrt(x). 605 | | uint256 xAux = uint256(x); 606 | | result = 1; 607 | | if (xAux >= 0x100000000000000000000000000000000) { 608 | | xAux >>= 128; 609 | | result <<= 64; 610 | | } 611 | | if (xAux >= 0x10000000000000000) { 612 | | xAux >>= 64; 613 | | result <<= 32; 614 | | } 615 | | if (xAux >= 0x100000000) { 616 | | xAux >>= 32; 617 | | result <<= 16; 618 | | } 619 | | if (xAux >= 0x10000) { 620 | | xAux >>= 16; 621 | | result <<= 8; 622 | | } 623 | | if (xAux >= 0x100) { 624 | | xAux >>= 8; 625 | | result <<= 4; 626 | | } 627 | | if (xAux >= 0x10) { 628 | | xAux >>= 4; 629 | | result <<= 2; 630 | | } 631 | | if (xAux >= 0x8) { 632 | | result <<= 1; 633 | | } 634 | | 635 | | // The operations can never overflow because the result is max 2^127 when it enters this block. 636 | | unchecked { 637 | | result = (result + x / result) >> 1; 638 | | result = (result + x / result) >> 1; 639 | | result = (result + x / result) >> 1; 640 | | result = (result + x / result) >> 1; 641 | | result = (result + x / result) >> 1; 642 | | result = (result + x / result) >> 1; 643 | | result = (result + x / result) >> 1; // Seven iterations should be enough 644 | | uint256 roundedDownResult = x / result; 645 | | return result >= roundedDownResult ? roundedDownResult : result; 646 | | } 647 | | } 648 | | } 649 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/node_modules/prb-math/contracts/PRBMathUD60x18.sol 1 | | // SPDX-License-Identifier: Unlicense 2 | | pragma solidity >=0.8.4; 3 | | 4 | | import "./PRBMath.sol"; 5 | | 6 | | /// @title PRBMathUD60x18 7 | | /// @author Paul Razvan Berg 8 | | /// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18 9 | | /// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60 10 | | /// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the 11 | | /// maximum values permitted by the Solidity type uint256. 12 | * | library PRBMathUD60x18 { 13 | | /// @dev Half the SCALE number. 14 | * | uint256 internal constant HALF_SCALE = 5e17; 15 | | 16 | | /// @dev log2(e) as an unsigned 60.18-decimal fixed-point number. 17 | | uint256 internal constant LOG2_E = 1_442695040888963407; 18 | | 19 | | /// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have. 20 | | uint256 internal constant MAX_UD60x18 = 21 | | 115792089237316195423570985008687907853269984665640564039457_584007913129639935; 22 | | 23 | | /// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have. 24 | | uint256 internal constant MAX_WHOLE_UD60x18 = 25 | | 115792089237316195423570985008687907853269984665640564039457_000000000000000000; 26 | | 27 | | /// @dev How many trailing decimals can be represented. 28 | * | uint256 internal constant SCALE = 1e18; 29 | | 30 | | /// @notice Calculates the arithmetic average of x and y, rounding down. 31 | | /// @param x The first operand as an unsigned 60.18-decimal fixed-point number. 32 | | /// @param y The second operand as an unsigned 60.18-decimal fixed-point number. 33 | | /// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number. 34 | | function avg(uint256 x, uint256 y) internal pure returns (uint256 result) { 35 | | // The operations can never overflow. 36 | | unchecked { 37 | | // The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need 38 | | // to do this because if both numbers are odd, the 0.5 remainder gets truncated twice. 39 | | result = (x >> 1) + (y >> 1) + (x & y & 1); 40 | | } 41 | | } 42 | | 43 | | /// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x. 44 | | /// 45 | | /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts. 46 | | /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. 47 | | /// 48 | | /// Requirements: 49 | | /// - x must be less than or equal to MAX_WHOLE_UD60x18. 50 | | /// 51 | | /// @param x The unsigned 60.18-decimal fixed-point number to ceil. 52 | | /// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number. 53 | | function ceil(uint256 x) internal pure returns (uint256 result) { 54 | | if (x > MAX_WHOLE_UD60x18) { 55 | | revert PRBMathUD60x18__CeilOverflow(x); 56 | | } 57 | | assembly { 58 | | // Equivalent to "x % SCALE" but faster. 59 | | let remainder := mod(x, SCALE) 60 | | 61 | | // Equivalent to "SCALE - remainder" but faster. 62 | | let delta := sub(SCALE, remainder) 63 | | 64 | | // Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster. 65 | | result := add(x, mul(delta, gt(remainder, 0))) 66 | | } 67 | | } 68 | | 69 | | /// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number. 70 | | /// 71 | | /// @dev Uses mulDiv to enable overflow-safe multiplication and division. 72 | | /// 73 | | /// Requirements: 74 | | /// - The denominator cannot be zero. 75 | | /// 76 | | /// @param x The numerator as an unsigned 60.18-decimal fixed-point number. 77 | | /// @param y The denominator as an unsigned 60.18-decimal fixed-point number. 78 | | /// @param result The quotient as an unsigned 60.18-decimal fixed-point number. 79 | | function div(uint256 x, uint256 y) internal pure returns (uint256 result) { 80 | | result = PRBMath.mulDiv(x, SCALE, y); 81 | | } 82 | | 83 | | /// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number. 84 | | /// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant). 85 | | function e() internal pure returns (uint256 result) { 86 | | result = 2_718281828459045235; 87 | | } 88 | | 89 | | /// @notice Calculates the natural exponent of x. 90 | | /// 91 | | /// @dev Based on the insight that e^x = 2^(x * log2(e)). 92 | | /// 93 | | /// Requirements: 94 | | /// - All from "log2". 95 | | /// - x must be less than 133.084258667509499441. 96 | | /// 97 | | /// @param x The exponent as an unsigned 60.18-decimal fixed-point number. 98 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 99 | | function exp(uint256 x) internal pure returns (uint256 result) { 100 | | // Without this check, the value passed to "exp2" would be greater than 192. 101 | | if (x >= 133_084258667509499441) { 102 | | revert PRBMathUD60x18__ExpInputTooBig(x); 103 | | } 104 | | 105 | | // Do the fixed-point multiplication inline to save gas. 106 | | unchecked { 107 | | uint256 doubleScaleProduct = x * LOG2_E; 108 | | result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE); 109 | | } 110 | | } 111 | | 112 | | /// @notice Calculates the binary exponent of x using the binary fraction method. 113 | | /// 114 | | /// @dev See https://ethereum.stackexchange.com/q/79903/24693. 115 | | /// 116 | | /// Requirements: 117 | | /// - x must be 192 or less. 118 | | /// - The result must fit within MAX_UD60x18. 119 | | /// 120 | | /// @param x The exponent as an unsigned 60.18-decimal fixed-point number. 121 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 122 | * | function exp2(uint256 x) internal pure returns (uint256 result) { 123 | | // 2^192 doesn't fit within the 192.64-bit format used internally in this function. 124 | * | if (x >= 192e18) { 125 | | revert PRBMathUD60x18__Exp2InputTooBig(x); 126 | | } 127 | | 128 | * | unchecked { 129 | | // Convert x to the 192.64-bit fixed-point format. 130 | * | uint256 x192x64 = (x << 64) / SCALE; 131 | | 132 | | // Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation. 133 | * | result = PRBMath.exp2(x192x64); 134 | | } 135 | | } 136 | | 137 | | /// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x. 138 | | /// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts. 139 | | /// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions. 140 | | /// @param x The unsigned 60.18-decimal fixed-point number to floor. 141 | | /// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number. 142 | | function floor(uint256 x) internal pure returns (uint256 result) { 143 | | assembly { 144 | | // Equivalent to "x % SCALE" but faster. 145 | | let remainder := mod(x, SCALE) 146 | | 147 | | // Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster. 148 | | result := sub(x, mul(remainder, gt(remainder, 0))) 149 | | } 150 | | } 151 | | 152 | | /// @notice Yields the excess beyond the floor of x. 153 | | /// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part. 154 | | /// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of. 155 | | /// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number. 156 | | function frac(uint256 x) internal pure returns (uint256 result) { 157 | | assembly { 158 | | result := mod(x, SCALE) 159 | | } 160 | | } 161 | | 162 | | /// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation. 163 | | /// 164 | | /// @dev Requirements: 165 | | /// - x must be less than or equal to MAX_UD60x18 divided by SCALE. 166 | | /// 167 | | /// @param x The basic integer to convert. 168 | | /// @param result The same number in unsigned 60.18-decimal fixed-point representation. 169 | | function fromUint(uint256 x) internal pure returns (uint256 result) { 170 | | unchecked { 171 | | if (x > MAX_UD60x18 / SCALE) { 172 | | revert PRBMathUD60x18__FromUintOverflow(x); 173 | | } 174 | | result = x * SCALE; 175 | | } 176 | | } 177 | | 178 | | /// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down. 179 | | /// 180 | | /// @dev Requirements: 181 | | /// - x * y must fit within MAX_UD60x18, lest it overflows. 182 | | /// 183 | | /// @param x The first operand as an unsigned 60.18-decimal fixed-point number. 184 | | /// @param y The second operand as an unsigned 60.18-decimal fixed-point number. 185 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 186 | | function gm(uint256 x, uint256 y) internal pure returns (uint256 result) { 187 | | if (x == 0) { 188 | | return 0; 189 | | } 190 | | 191 | | unchecked { 192 | | // Checking for overflow this way is faster than letting Solidity do it. 193 | | uint256 xy = x * y; 194 | | if (xy / x != y) { 195 | | revert PRBMathUD60x18__GmOverflow(x, y); 196 | | } 197 | | 198 | | // We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE 199 | | // during multiplication. See the comments within the "sqrt" function. 200 | | result = PRBMath.sqrt(xy); 201 | | } 202 | | } 203 | | 204 | | /// @notice Calculates 1 / x, rounding toward zero. 205 | | /// 206 | | /// @dev Requirements: 207 | | /// - x cannot be zero. 208 | | /// 209 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse. 210 | | /// @return result The inverse as an unsigned 60.18-decimal fixed-point number. 211 | | function inv(uint256 x) internal pure returns (uint256 result) { 212 | | unchecked { 213 | | // 1e36 is SCALE * SCALE. 214 | | result = 1e36 / x; 215 | | } 216 | | } 217 | | 218 | | /// @notice Calculates the natural logarithm of x. 219 | | /// 220 | | /// @dev Based on the insight that ln(x) = log2(x) / log2(e). 221 | | /// 222 | | /// Requirements: 223 | | /// - All from "log2". 224 | | /// 225 | | /// Caveats: 226 | | /// - All from "log2". 227 | | /// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision. 228 | | /// 229 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm. 230 | | /// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number. 231 | | function ln(uint256 x) internal pure returns (uint256 result) { 232 | | // Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x) 233 | | // can return is 196205294292027477728. 234 | | unchecked { 235 | | result = (log2(x) * SCALE) / LOG2_E; 236 | | } 237 | | } 238 | | 239 | | /// @notice Calculates the common logarithm of x. 240 | | /// 241 | | /// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common 242 | | /// logarithm based on the insight that log10(x) = log2(x) / log2(10). 243 | | /// 244 | | /// Requirements: 245 | | /// - All from "log2". 246 | | /// 247 | | /// Caveats: 248 | | /// - All from "log2". 249 | | /// 250 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm. 251 | | /// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number. 252 | | function log10(uint256 x) internal pure returns (uint256 result) { 253 | | if (x < SCALE) { 254 | | revert PRBMathUD60x18__LogInputTooSmall(x); 255 | | } 256 | | 257 | | // Note that the "mul" in this block is the assembly multiplication operation, not the "mul" function defined 258 | | // in this contract. 259 | | // prettier-ignore 260 | | assembly { 261 | | switch x 262 | | case 1 { result := mul(SCALE, sub(0, 18)) } 263 | | case 10 { result := mul(SCALE, sub(1, 18)) } 264 | | case 100 { result := mul(SCALE, sub(2, 18)) } 265 | | case 1000 { result := mul(SCALE, sub(3, 18)) } 266 | | case 10000 { result := mul(SCALE, sub(4, 18)) } 267 | | case 100000 { result := mul(SCALE, sub(5, 18)) } 268 | | case 1000000 { result := mul(SCALE, sub(6, 18)) } 269 | | case 10000000 { result := mul(SCALE, sub(7, 18)) } 270 | | case 100000000 { result := mul(SCALE, sub(8, 18)) } 271 | | case 1000000000 { result := mul(SCALE, sub(9, 18)) } 272 | | case 10000000000 { result := mul(SCALE, sub(10, 18)) } 273 | | case 100000000000 { result := mul(SCALE, sub(11, 18)) } 274 | | case 1000000000000 { result := mul(SCALE, sub(12, 18)) } 275 | | case 10000000000000 { result := mul(SCALE, sub(13, 18)) } 276 | | case 100000000000000 { result := mul(SCALE, sub(14, 18)) } 277 | | case 1000000000000000 { result := mul(SCALE, sub(15, 18)) } 278 | | case 10000000000000000 { result := mul(SCALE, sub(16, 18)) } 279 | | case 100000000000000000 { result := mul(SCALE, sub(17, 18)) } 280 | | case 1000000000000000000 { result := 0 } 281 | | case 10000000000000000000 { result := SCALE } 282 | | case 100000000000000000000 { result := mul(SCALE, 2) } 283 | | case 1000000000000000000000 { result := mul(SCALE, 3) } 284 | | case 10000000000000000000000 { result := mul(SCALE, 4) } 285 | | case 100000000000000000000000 { result := mul(SCALE, 5) } 286 | | case 1000000000000000000000000 { result := mul(SCALE, 6) } 287 | | case 10000000000000000000000000 { result := mul(SCALE, 7) } 288 | | case 100000000000000000000000000 { result := mul(SCALE, 8) } 289 | | case 1000000000000000000000000000 { result := mul(SCALE, 9) } 290 | | case 10000000000000000000000000000 { result := mul(SCALE, 10) } 291 | | case 100000000000000000000000000000 { result := mul(SCALE, 11) } 292 | | case 1000000000000000000000000000000 { result := mul(SCALE, 12) } 293 | | case 10000000000000000000000000000000 { result := mul(SCALE, 13) } 294 | | case 100000000000000000000000000000000 { result := mul(SCALE, 14) } 295 | | case 1000000000000000000000000000000000 { result := mul(SCALE, 15) } 296 | | case 10000000000000000000000000000000000 { result := mul(SCALE, 16) } 297 | | case 100000000000000000000000000000000000 { result := mul(SCALE, 17) } 298 | | case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) } 299 | | case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) } 300 | | case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) } 301 | | case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) } 302 | | case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) } 303 | | case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) } 304 | | case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) } 305 | | case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) } 306 | | case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) } 307 | | case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) } 308 | | case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) } 309 | | case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) } 310 | | case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) } 311 | | case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) } 312 | | case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) } 313 | | case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) } 314 | | case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) } 315 | | case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) } 316 | | case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) } 317 | | case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) } 318 | | case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) } 319 | | case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) } 320 | | case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) } 321 | | case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) } 322 | | case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) } 323 | | case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) } 324 | | case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) } 325 | | case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) } 326 | | case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) } 327 | | case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) } 328 | | case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) } 329 | | case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) } 330 | | case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) } 331 | | case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) } 332 | | case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) } 333 | | case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) } 334 | | case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) } 335 | | case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) } 336 | | case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) } 337 | | case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) } 338 | | case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) } 339 | | case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) } 340 | | default { 341 | | result := MAX_UD60x18 342 | | } 343 | | } 344 | | 345 | | if (result == MAX_UD60x18) { 346 | | // Do the fixed-point division inline to save gas. The denominator is log2(10). 347 | | unchecked { 348 | | result = (log2(x) * SCALE) / 3_321928094887362347; 349 | | } 350 | | } 351 | | } 352 | | 353 | | /// @notice Calculates the binary logarithm of x. 354 | | /// 355 | | /// @dev Based on the iterative approximation algorithm. 356 | | /// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation 357 | | /// 358 | | /// Requirements: 359 | | /// - x must be greater than or equal to SCALE, otherwise the result would be negative. 360 | | /// 361 | | /// Caveats: 362 | | /// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation. 363 | | /// 364 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm. 365 | | /// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number. 366 | * | function log2(uint256 x) internal pure returns (uint256 result) { 367 | * | if (x < SCALE) { 368 | | revert PRBMathUD60x18__LogInputTooSmall(x); 369 | | } 370 | * | unchecked { 371 | | // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n). 372 | * | uint256 n = PRBMath.mostSignificantBit(x / SCALE); 373 | | 374 | | // The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow 375 | | // because n is maximum 255 and SCALE is 1e18. 376 | * | result = n * SCALE; 377 | | 378 | | // This is y = x * 2^(-n). 379 | * | uint256 y = x >> n; 380 | | 381 | | // If y = 1, the fractional part is zero. 382 | * | if (y == SCALE) { 383 | * | return result; 384 | | } 385 | | 386 | | // Calculate the fractional part via the iterative approximation. 387 | | // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster. 388 | * | for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) { 389 | * | y = (y * y) / SCALE; 390 | | 391 | | // Is y^2 > 2 and so in the range [2,4)? 392 | * | if (y >= 2 * SCALE) { 393 | | // Add the 2^(-m) factor to the logarithm. 394 | * | result += delta; 395 | | 396 | | // Corresponds to z/2 on Wikipedia. 397 | * | y >>= 1; 398 | | } 399 | | } 400 | | } 401 | | } 402 | | 403 | | /// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal 404 | | /// fixed-point number. 405 | | /// @dev See the documentation for the "PRBMath.mulDivFixedPoint" function. 406 | | /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number. 407 | | /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number. 408 | | /// @return result The product as an unsigned 60.18-decimal fixed-point number. 409 | * | function mul(uint256 x, uint256 y) internal pure returns (uint256 result) { 410 | * | result = PRBMath.mulDivFixedPoint(x, y); 411 | | } 412 | | 413 | | /// @notice Returns PI as an unsigned 60.18-decimal fixed-point number. 414 | | function pi() internal pure returns (uint256 result) { 415 | | result = 3_141592653589793238; 416 | | } 417 | | 418 | | /// @notice Raises x to the power of y. 419 | | /// 420 | | /// @dev Based on the insight that x^y = 2^(log2(x) * y). 421 | | /// 422 | | /// Requirements: 423 | | /// - All from "exp2", "log2" and "mul". 424 | | /// 425 | | /// Caveats: 426 | | /// - All from "exp2", "log2" and "mul". 427 | | /// - Assumes 0^0 is 1. 428 | | /// 429 | | /// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number. 430 | | /// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number. 431 | | /// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number. 432 | * | function pow(uint256 x, uint256 y) internal pure returns (uint256 result) { 433 | * | if (x == 0) { 434 | | result = y == 0 ? SCALE : uint256(0); 435 | | } else { 436 | * | result = exp2(mul(log2(x), y)); 437 | | } 438 | | } 439 | | 440 | | /// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the 441 | | /// famous algorithm "exponentiation by squaring". 442 | | /// 443 | | /// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring 444 | | /// 445 | | /// Requirements: 446 | | /// - The result must fit within MAX_UD60x18. 447 | | /// 448 | | /// Caveats: 449 | | /// - All from "mul". 450 | | /// - Assumes 0^0 is 1. 451 | | /// 452 | | /// @param x The base as an unsigned 60.18-decimal fixed-point number. 453 | | /// @param y The exponent as an uint256. 454 | | /// @return result The result as an unsigned 60.18-decimal fixed-point number. 455 | | function powu(uint256 x, uint256 y) internal pure returns (uint256 result) { 456 | | // Calculate the first iteration of the loop in advance. 457 | | result = y & 1 > 0 ? x : SCALE; 458 | | 459 | | // Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster. 460 | | for (y >>= 1; y > 0; y >>= 1) { 461 | | x = PRBMath.mulDivFixedPoint(x, x); 462 | | 463 | | // Equivalent to "y % 2 == 1" but faster. 464 | | if (y & 1 > 0) { 465 | | result = PRBMath.mulDivFixedPoint(result, x); 466 | | } 467 | | } 468 | | } 469 | | 470 | | /// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number. 471 | | function scale() internal pure returns (uint256 result) { 472 | | result = SCALE; 473 | | } 474 | | 475 | | /// @notice Calculates the square root of x, rounding down. 476 | | /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method. 477 | | /// 478 | | /// Requirements: 479 | | /// - x must be less than MAX_UD60x18 / SCALE. 480 | | /// 481 | | /// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root. 482 | | /// @return result The result as an unsigned 60.18-decimal fixed-point . 483 | | function sqrt(uint256 x) internal pure returns (uint256 result) { 484 | | unchecked { 485 | | if (x > MAX_UD60x18 / SCALE) { 486 | | revert PRBMathUD60x18__SqrtOverflow(x); 487 | | } 488 | | // Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned 489 | | // 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root). 490 | | result = PRBMath.sqrt(x * SCALE); 491 | | } 492 | | } 493 | | 494 | | /// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process. 495 | | /// @param x The unsigned 60.18-decimal fixed-point number to convert. 496 | | /// @return result The same number in basic integer form. 497 | | function toUint(uint256 x) internal pure returns (uint256 result) { 498 | | unchecked { 499 | | result = x / SCALE; 500 | | } 501 | | } 502 | | } 503 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/adl/AdlUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | 8 | | import "../order/OrderStoreUtils.sol"; 9 | | import "../order/OrderEventUtils.sol"; 10 | | import "../position/PositionUtils.sol"; 11 | | import "../position/PositionStoreUtils.sol"; 12 | | import "../nonce/NonceUtils.sol"; 13 | | import "../callback/CallbackUtils.sol"; 14 | | 15 | | // @title AdlUtils 16 | | // @dev Library to help with auto-deleveraging 17 | | // This is particularly for markets with an index token that is different from 18 | | // the long token 19 | | // 20 | | // For example, if there is a DOGE / USD perp market with ETH as the long token 21 | | // it would be possible for the price of DOGE to increase faster than the price of 22 | | // ETH 23 | | // 24 | | // In this scenario, profitable positions should be closed through ADL to ensure 25 | | // that the system remains fully solvent 26 | * | library AdlUtils { 27 | | using SafeCast for int256; 28 | | using Array for uint256[]; 29 | | using Market for Market.Props; 30 | | using Position for Position.Props; 31 | | 32 | | using EventUtils for EventUtils.AddressItems; 33 | | using EventUtils for EventUtils.UintItems; 34 | | using EventUtils for EventUtils.IntItems; 35 | | using EventUtils for EventUtils.BoolItems; 36 | | using EventUtils for EventUtils.Bytes32Items; 37 | | using EventUtils for EventUtils.BytesItems; 38 | | using EventUtils for EventUtils.StringItems; 39 | | 40 | | // @dev CreateAdlOrderParams struct used in createAdlOrder to avoid stack 41 | | // too deep errors 42 | | // 43 | | // @param dataStore DataStore 44 | | // @param orderStore OrderStore 45 | | // @param account the account to reduce the position for 46 | | // @param market the position's market 47 | | // @param collateralToken the position's collateralToken 48 | | // @param isLong whether the position is long or short 49 | | // @param sizeDeltaUsd the size to reduce the position by 50 | | // @param updatedAtBlock the block to set the order's updatedAtBlock to 51 | | struct CreateAdlOrderParams { 52 | | DataStore dataStore; 53 | | EventEmitter eventEmitter; 54 | | address account; 55 | | address market; 56 | | address collateralToken; 57 | | bool isLong; 58 | | uint256 sizeDeltaUsd; 59 | | uint256 updatedAtBlock; 60 | | uint256 updatedAtTime; 61 | | } 62 | | 63 | | // @dev Multiple positions may need to be reduced to ensure that the pending 64 | | // profits does not exceed the allowed thresholds 65 | | // 66 | | // This automatic reduction of positions can only be done if the pool is in a state 67 | | // where auto-deleveraging is required 68 | | // 69 | | // This function checks the pending profit state and updates an isAdlEnabled 70 | | // flag to avoid having to repeatedly validate whether auto-deleveraging is required 71 | | // 72 | | // Once the pending profit has been reduced below the threshold this function can 73 | | // be called again to clear the flag 74 | | // 75 | | // The ADL check would be possible to do in AdlHandler.executeAdl as well 76 | | // but with that order keepers could use stale oracle prices to prove that 77 | | // an ADL state is possible 78 | | // 79 | | // Having this function allows any order keeper to disable ADL if prices 80 | | // have updated such that ADL is no longer needed 81 | | // 82 | | // @param dataStore DataStore 83 | | // @param eventEmitter EventEmitter 84 | | // @param oracle Oracle 85 | | // @param market address of the market to check 86 | | // @param isLong indicates whether to check the long or short side of the market 87 | * | function updateAdlState( 88 | | DataStore dataStore, 89 | | EventEmitter eventEmitter, 90 | | Oracle oracle, 91 | | address market, 92 | | bool isLong 93 | * | ) internal { 94 | * | uint256 latestAdlTime = getLatestAdlTime(dataStore, market, isLong); 95 | | 96 | * | if (oracle.maxTimestamp() < latestAdlTime) { 97 | | revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime); 98 | | } 99 | | 100 | * | Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market); 101 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, _market); 102 | | // if the MAX_PNL_FACTOR_FOR_ADL is set to be higher than MAX_PNL_FACTOR_FOR_WITHDRAWALS 103 | | // it is possible for a pool to be in a state where withdrawals and ADL is not allowed 104 | | // this is similar to the case where there is a large amount of open positions relative 105 | | // to the amount of tokens in the pool 106 | * | (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded( 107 | * | dataStore, 108 | * | _market, 109 | * | prices, 110 | * | isLong, 111 | | Keys.MAX_PNL_FACTOR_FOR_ADL 112 | | ); 113 | | 114 | * | setIsAdlEnabled(dataStore, market, isLong, shouldEnableAdl); 115 | | // since the latest ADL at is always updated, an ADL keeper could 116 | | // continually cause the latest ADL time to be updated and prevent 117 | | // ADL orders from being executed, however, this may be preferrable 118 | | // over a case where stale prices could be used by ADL keepers 119 | | // to execute orders 120 | | // as such updating of the ADL time is allowed and it is expected 121 | | // that ADL keepers will keep this time updated so that latest prices 122 | | // will be used for ADL 123 | * | setLatestAdlAt(dataStore, market, isLong, Chain.currentTimestamp()); 124 | | 125 | * | emitAdlStateUpdated(eventEmitter, market, isLong, pnlToPoolFactor, maxPnlFactor, shouldEnableAdl); 126 | | } 127 | | 128 | | // @dev Construct an ADL order 129 | | // 130 | | // A decrease order is used to reduce a profitable position 131 | | // 132 | | // @param params CreateAdlOrderParams 133 | | // @return the key of the created order 134 | * | function createAdlOrder(CreateAdlOrderParams memory params) internal returns (bytes32) { 135 | * | bytes32 positionKey = Position.getPositionKey(params.account, params.market, params.collateralToken, params.isLong); 136 | * | Position.Props memory position = PositionStoreUtils.get(params.dataStore, positionKey); 137 | | 138 | * | if (params.sizeDeltaUsd > position.sizeInUsd()) { 139 | | revert Errors.InvalidSizeDeltaForAdl(params.sizeDeltaUsd, position.sizeInUsd()); 140 | | } 141 | | 142 | * | Order.Addresses memory addresses = Order.Addresses( 143 | * | params.account, // account 144 | * | params.account, // receiver 145 | * | params.account, // cancellationReceiver 146 | * | CallbackUtils.getSavedCallbackContract(params.dataStore, params.account, params.market), // callbackContract 147 | * | address(0), // uiFeeReceiver 148 | * | params.market, // market 149 | * | position.collateralToken(), // initialCollateralToken 150 | * | new address[](0) // swapPath 151 | | ); 152 | | 153 | | // no slippage is set for this order, it may be preferrable for ADL orders 154 | | // to be executed, in case of large price impact, the user could be refunded 155 | | // through a protocol fund if required, this amount could later be claimed 156 | | // from the price impact pool, this claiming process should be added if 157 | | // required 158 | | // 159 | | // setting a maximum price impact that will work for majority of cases 160 | | // may also be challenging since the price impact would vary based on the 161 | | // amount of collateral being swapped 162 | | // 163 | | // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken 164 | | // because fees are calculated with reference to the collateral token 165 | | // fees are deducted from the output amount if the output token is the same as the 166 | | // collateral token 167 | | // swapping the pnl token to the collateral token helps to ensure fees can be paid 168 | | // using the realized profit 169 | * | Order.Numbers memory numbers = Order.Numbers( 170 | * | Order.OrderType.MarketDecrease, // orderType 171 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType 172 | * | params.sizeDeltaUsd, // sizeDeltaUsd 173 | * | 0, // initialCollateralDeltaAmount 174 | * | 0, // triggerPrice 175 | * | position.isLong() ? 0 : type(uint256).max, // acceptablePrice 176 | * | 0, // executionFee 177 | * | params.dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit 178 | * | 0, // minOutputAmount 179 | * | params.updatedAtBlock, // updatedAtBlock 180 | * | params.updatedAtTime // updatedAtTime 181 | | ); 182 | | 183 | * | Order.Flags memory flags = Order.Flags( 184 | * | position.isLong(), // isLong 185 | * | true, // shouldUnwrapNativeToken 186 | * | false, // isFrozen 187 | * | false // autoCancel 188 | | ); 189 | | 190 | * | Order.Props memory order = Order.Props( 191 | * | addresses, 192 | * | numbers, 193 | * | flags 194 | | ); 195 | | 196 | * | bytes32 key = NonceUtils.getNextKey(params.dataStore); 197 | * | OrderStoreUtils.set(params.dataStore, key, order); 198 | | 199 | * | OrderEventUtils.emitOrderCreated(params.eventEmitter, key, order); 200 | | 201 | * | return key; 202 | | } 203 | | 204 | | // @dev validate if the requested ADL can be executed 205 | | // 206 | | // @param dataStore DataStore 207 | | // @param oracle Oracle 208 | | // @param market address of the market to check 209 | | // @param isLong indicates whether to check the long or short side of the market 210 | * | function validateAdl( 211 | | DataStore dataStore, 212 | | Oracle oracle, 213 | | address market, 214 | | bool isLong 215 | * | ) internal view { 216 | * | bool isAdlEnabled = AdlUtils.getIsAdlEnabled(dataStore, market, isLong); 217 | * | if (!isAdlEnabled) { 218 | * | revert Errors.AdlNotEnabled(); 219 | | } 220 | | 221 | * | uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong); 222 | * | if (oracle.maxTimestamp() < latestAdlTime) { 223 | | revert Errors.OracleTimestampsAreSmallerThanRequired(oracle.maxTimestamp(), latestAdlTime); 224 | | } 225 | | } 226 | | 227 | | // @dev get the latest time at which the ADL flag was updated 228 | | // 229 | | // @param dataStore DataStore 230 | | // @param market address of the market to check 231 | | // @param isLong indicates whether to check the long or short side of the market 232 | | // 233 | | // @return the latest time at which the ADL flag was updated 234 | * | function getLatestAdlTime(DataStore dataStore, address market, bool isLong) internal view returns (uint256) { 235 | * | return dataStore.getUint(Keys.latestAdlAtKey(market, isLong)); 236 | | } 237 | | 238 | | // @dev set the latest time at which the ADL flag was updated 239 | | // 240 | | // @param dataStore DataStore 241 | | // @param market address of the market to check 242 | | // @param isLong indicates whether to check the long or short side of the market 243 | | // @param value the latest time value 244 | | // 245 | | // @return the latest time value 246 | * | function setLatestAdlAt(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) { 247 | * | return dataStore.setUint(Keys.latestAdlAtKey(market, isLong), value); 248 | | } 249 | | 250 | | // @dev get whether ADL is enabled 251 | | // 252 | | // @param dataStore DataStore 253 | | // @param market address of the market to check 254 | | // @param isLong indicates whether to check the long or short side of the market 255 | | // 256 | | // @return whether ADL is enabled 257 | * | function getIsAdlEnabled(DataStore dataStore, address market, bool isLong) internal view returns (bool) { 258 | * | return dataStore.getBool(Keys.isAdlEnabledKey(market, isLong)); 259 | | } 260 | | 261 | | // @dev set whether ADL is enabled 262 | | // 263 | | // @param dataStore DataStore 264 | | // @param market address of the market to check 265 | | // @param isLong indicates whether to check the long or short side of the market 266 | | // @param value whether ADL is enabled 267 | | // 268 | | // @return whether ADL is enabled 269 | * | function setIsAdlEnabled(DataStore dataStore, address market, bool isLong, bool value) internal returns (bool) { 270 | * | return dataStore.setBool(Keys.isAdlEnabledKey(market, isLong), value); 271 | | } 272 | | 273 | | // @dev emit ADL state update events 274 | | // 275 | | // @param eventEmitter EventEmitter 276 | | // @param market address of the market for the ADL state update 277 | | // @param isLong indicates the ADL state update is for the long or short side of the market 278 | | // @param pnlToPoolFactor the ratio of PnL to pool value 279 | | // @param maxPnlFactor the max PnL factor 280 | | // @param shouldEnableAdl whether ADL was enabled or disabled 281 | * | function emitAdlStateUpdated( 282 | | EventEmitter eventEmitter, 283 | | address market, 284 | | bool isLong, 285 | | int256 pnlToPoolFactor, 286 | | uint256 maxPnlFactor, 287 | | bool shouldEnableAdl 288 | * | ) internal { 289 | * | EventUtils.EventLogData memory eventData; 290 | | 291 | * | eventData.intItems.initItems(1); 292 | * | eventData.intItems.setItem(0, "pnlToPoolFactor", pnlToPoolFactor); 293 | | 294 | * | eventData.uintItems.initItems(1); 295 | * | eventData.uintItems.setItem(0, "maxPnlFactor", maxPnlFactor); 296 | | 297 | * | eventData.boolItems.initItems(2); 298 | * | eventData.boolItems.setItem(0, "isLong", isLong); 299 | * | eventData.boolItems.setItem(1, "shouldEnableAdl", shouldEnableAdl); 300 | | 301 | * | eventEmitter.emitEventLog1( 302 | | "AdlStateUpdated", 303 | * | Cast.toBytes32(market), 304 | * | eventData 305 | | ); 306 | | } 307 | | } 308 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/bank/Bank.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | | 8 | | import "../token/TokenUtils.sol"; 9 | | import "../role/RoleModule.sol"; 10 | | 11 | | // @title Bank 12 | | // @dev Contract to handle storing and transferring of tokens 13 | | contract Bank is RoleModule { 14 | | using SafeERC20 for IERC20; 15 | | 16 | | DataStore public immutable dataStore; 17 | | 18 | | constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) { 19 | | dataStore = _dataStore; 20 | | } 21 | | 22 | | receive() external payable { 23 | | address wnt = TokenUtils.wnt(dataStore); 24 | | if (msg.sender != wnt) { 25 | | revert Errors.InvalidNativeTokenSender(msg.sender); 26 | | } 27 | | } 28 | | 29 | | // @dev transfer tokens from this contract to a receiver 30 | | // 31 | | // @param token the token to transfer 32 | | // @param amount the amount to transfer 33 | | // @param receiver the address to transfer to 34 | * | function transferOut( 35 | | address token, 36 | | address receiver, 37 | | uint256 amount 38 | | ) external onlyController { 39 | * | _transferOut(token, receiver, amount); 40 | | } 41 | | 42 | | // @dev transfer tokens from this contract to a receiver 43 | | // handles native token transfers as well 44 | | // 45 | | // @param token the token to transfer 46 | | // @param amount the amount to transfer 47 | | // @param receiver the address to transfer to 48 | | // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token 49 | | // before transferring 50 | * | function transferOut( 51 | | address token, 52 | | address receiver, 53 | | uint256 amount, 54 | | bool shouldUnwrapNativeToken 55 | * | ) external onlyController { 56 | * | address wnt = TokenUtils.wnt(dataStore); 57 | | 58 | * | if (token == wnt && shouldUnwrapNativeToken) { 59 | | _transferOutNativeToken(token, receiver, amount); 60 | | } else { 61 | * | _transferOut(token, receiver, amount); 62 | | } 63 | | } 64 | | 65 | | // @dev transfer native tokens from this contract to a receiver 66 | | // 67 | | // @param token the token to transfer 68 | | // @param amount the amount to transfer 69 | | // @param receiver the address to transfer to 70 | | // @param shouldUnwrapNativeToken whether to unwrap the wrapped native token 71 | | // before transferring 72 | | function transferOutNativeToken( 73 | | address receiver, 74 | | uint256 amount 75 | | ) external onlyController { 76 | | address wnt = TokenUtils.wnt(dataStore); 77 | | _transferOutNativeToken(wnt, receiver, amount); 78 | | } 79 | | 80 | | // @dev transfer tokens from this contract to a receiver 81 | | // 82 | | // @param token the token to transfer 83 | | // @param amount the amount to transfer 84 | | // @param receiver the address to transfer to 85 | * | function _transferOut( 86 | | address token, 87 | | address receiver, 88 | | uint256 amount 89 | | ) internal { 90 | * | if (receiver == address(this)) { 91 | | revert Errors.SelfTransferNotSupported(receiver); 92 | | } 93 | | 94 | * | TokenUtils.transfer(dataStore, token, receiver, amount); 95 | | 96 | * | _afterTransferOut(token); 97 | | } 98 | | 99 | | // @dev unwrap wrapped native tokens and transfer the native tokens from 100 | | // this contract to a receiver 101 | | // 102 | | // @param token the token to transfer 103 | | // @param amount the amount to transfer 104 | | // @param receiver the address to transfer to 105 | | function _transferOutNativeToken( 106 | | address token, 107 | | address receiver, 108 | | uint256 amount 109 | | ) internal { 110 | | if (receiver == address(this)) { 111 | | revert Errors.SelfTransferNotSupported(receiver); 112 | | } 113 | | 114 | | TokenUtils.withdrawAndSendNativeToken( 115 | | dataStore, 116 | | token, 117 | | receiver, 118 | | amount 119 | | ); 120 | | 121 | | _afterTransferOut(token); 122 | | } 123 | | 124 | * | function _afterTransferOut(address /* token */) internal virtual {} 125 | | } 126 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/bank/StrictBank.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | | 8 | | import "./Bank.sol"; 9 | | 10 | | // @title StrictBank 11 | | // @dev a stricter version of Bank 12 | | // 13 | | // the Bank contract does not have functions to validate the amount of tokens 14 | | // transferred in 15 | | // the Bank contract will mainly assume that safeTransferFrom calls work correctly 16 | | // and that tokens were transferred into it if there was no revert 17 | | // 18 | | // the StrictBank contract keeps track of its internal token balance 19 | | // and uses recordTransferIn to compare its change in balance and return 20 | | // the amount of tokens received 21 | * | contract StrictBank is Bank { 22 | | using SafeERC20 for IERC20; 23 | | 24 | | // used to record token balances to evaluate amounts transferred in 25 | | mapping (address => uint256) public tokenBalances; 26 | | 27 | | constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {} 28 | | 29 | | // @dev records a token transfer into the contract 30 | | // @param token the token to record the transfer for 31 | | // @return the amount of tokens transferred in 32 | * | function recordTransferIn(address token) external onlyController returns (uint256) { 33 | * | return _recordTransferIn(token); 34 | | } 35 | | 36 | | // @dev this can be used to update the tokenBalances in case of token burns 37 | | // or similar balance changes 38 | | // the prevBalance is not validated to be more than the nextBalance as this 39 | | // could allow someone to block this call by transferring into the contract 40 | | // @param token the token to record the burn for 41 | | // @return the new balance 42 | * | function syncTokenBalance(address token) external onlyController returns (uint256) { 43 | * | uint256 nextBalance = IERC20(token).balanceOf(address(this)); 44 | * | tokenBalances[token] = nextBalance; 45 | * | return nextBalance; 46 | | } 47 | | 48 | | // @dev records a token transfer into the contract 49 | | // @param token the token to record the transfer for 50 | | // @return the amount of tokens transferred in 51 | * | function _recordTransferIn(address token) internal returns (uint256) { 52 | * | uint256 prevBalance = tokenBalances[token]; 53 | * | uint256 nextBalance = IERC20(token).balanceOf(address(this)); 54 | * | tokenBalances[token] = nextBalance; 55 | | 56 | * | return nextBalance - prevBalance; 57 | | } 58 | | 59 | | // @dev update the internal balance after tokens have been transferred out 60 | | // this is called from the Bank contract 61 | | // @param token the token that was transferred out 62 | * | function _afterTransferOut(address token) internal override { 63 | * | tokenBalances[token] = IERC20(token).balanceOf(address(this)); 64 | | } 65 | | } 66 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/CallbackUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/Address.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../data/Keys.sol"; 9 | | import "../error/ErrorUtils.sol"; 10 | | 11 | | import "./IOrderCallbackReceiver.sol"; 12 | | import "./IDepositCallbackReceiver.sol"; 13 | | import "./IWithdrawalCallbackReceiver.sol"; 14 | | import "./IShiftCallbackReceiver.sol"; 15 | | import "./IGasFeeCallbackReceiver.sol"; 16 | | import "./IGlvDepositCallbackReceiver.sol"; 17 | | 18 | | // @title CallbackUtils 19 | | // @dev most features require a two step process to complete 20 | | // the user first sends a request transaction, then a second transaction is sent 21 | | // by a keeper to execute the request 22 | | // 23 | | // to allow for better composability with other contracts, a callback contract 24 | | // can be specified to be called after request executions or cancellations 25 | | // 26 | | // in case it is necessary to add "before" callbacks, extra care should be taken 27 | | // to ensure that important state cannot be changed during the before callback 28 | | // for example, if an order can be cancelled in the "before" callback during 29 | | // order execution, it may lead to an order being executed even though the user 30 | | // was already refunded for its cancellation 31 | | // 32 | | // the details from callback errors are not processed to avoid cases where a malicious 33 | | // callback contract returns a very large value to cause transactions to run out of gas 34 | * | library CallbackUtils { 35 | | using Address for address; 36 | | using Deposit for Deposit.Props; 37 | | using Withdrawal for Withdrawal.Props; 38 | | using Shift for Shift.Props; 39 | | using Order for Order.Props; 40 | | using GlvDeposit for GlvDeposit.Props; 41 | | 42 | | event AfterDepositExecutionError(bytes32 key, Deposit.Props deposit); 43 | | event AfterDepositCancellationError(bytes32 key, Deposit.Props deposit); 44 | | 45 | | event AfterWithdrawalExecutionError(bytes32 key, Withdrawal.Props withdrawal); 46 | | event AfterWithdrawalCancellationError(bytes32 key, Withdrawal.Props withdrawal); 47 | | 48 | | event AfterShiftExecutionError(bytes32 key, Shift.Props shift); 49 | | event AfterShiftCancellationError(bytes32 key, Shift.Props shift); 50 | | 51 | | event AfterOrderExecutionError(bytes32 key, Order.Props order); 52 | | event AfterOrderCancellationError(bytes32 key, Order.Props order); 53 | | event AfterOrderFrozenError(bytes32 key, Order.Props order); 54 | | 55 | | event AfterGlvDepositExecutionError(bytes32 key, GlvDeposit.Props glvDeposit); 56 | | event AfterGlvDepositCancellationError(bytes32 key, GlvDeposit.Props glvDeposit); 57 | | 58 | | // @dev validate that the callbackGasLimit is less than the max specified value 59 | | // this is to prevent callback gas limits which are larger than the max gas limits per block 60 | | // as this would allow for callback contracts that can consume all gas and conditionally cause 61 | | // executions to fail 62 | | // @param dataStore DataStore 63 | | // @param callbackGasLimit the callback gas limit 64 | * | function validateCallbackGasLimit(DataStore dataStore, uint256 callbackGasLimit) internal view { 65 | * | uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT); 66 | * | if (callbackGasLimit > maxCallbackGasLimit) { 67 | | revert Errors.MaxCallbackGasLimitExceeded(callbackGasLimit, maxCallbackGasLimit); 68 | | } 69 | | } 70 | | 71 | * | function validateGasLeftForCallback(uint256 callbackGasLimit) internal view { 72 | * | uint256 gasToBeForwarded = gasleft() / 64 * 63; 73 | * | if (gasToBeForwarded < callbackGasLimit) { 74 | | revert Errors.InsufficientGasLeftForCallback(gasToBeForwarded, callbackGasLimit); 75 | | } 76 | | } 77 | | 78 | | function setSavedCallbackContract(DataStore dataStore, address account, address market, address callbackContract) internal { 79 | | dataStore.setAddress(Keys.savedCallbackContract(account, market), callbackContract); 80 | | } 81 | | 82 | * | function getSavedCallbackContract(DataStore dataStore, address account, address market) internal view returns (address) { 83 | * | return dataStore.getAddress(Keys.savedCallbackContract(account, market)); 84 | | } 85 | | 86 | * | function refundExecutionFee( 87 | | DataStore dataStore, 88 | | bytes32 key, 89 | | address callbackContract, 90 | | uint256 refundFeeAmount, 91 | | EventUtils.EventLogData memory eventData 92 | * | ) internal returns (bool) { 93 | * | if (!isValidCallbackContract(callbackContract)) { return false; } 94 | | 95 | * | uint256 gasLimit = dataStore.getUint(Keys.REFUND_EXECUTION_FEE_GAS_LIMIT); 96 | | 97 | * | try IGasFeeCallbackReceiver(callbackContract).refundExecutionFee{ gas: gasLimit, value: refundFeeAmount }( 98 | * | key, 99 | * | eventData 100 | | ) { 101 | * | return true; 102 | | } catch { 103 | | return false; 104 | | } 105 | | } 106 | | 107 | | // @dev called after a deposit execution 108 | | // @param key the key of the deposit 109 | | // @param deposit the deposit that was executed 110 | * | function afterDepositExecution( 111 | | bytes32 key, 112 | | Deposit.Props memory deposit, 113 | | EventUtils.EventLogData memory eventData 114 | | ) internal { 115 | * | if (!isValidCallbackContract(deposit.callbackContract())) { return; } 116 | | 117 | * | validateGasLeftForCallback(deposit.callbackGasLimit()); 118 | | 119 | * | try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositExecution{ gas: deposit.callbackGasLimit() }( 120 | * | key, 121 | * | deposit, 122 | * | eventData 123 | | ) { 124 | | } catch { 125 | | emit AfterDepositExecutionError(key, deposit); 126 | | } 127 | | } 128 | | 129 | | // @dev called after a deposit cancellation 130 | | // @param key the key of the deposit 131 | | // @param deposit the deposit that was cancelled 132 | * | function afterDepositCancellation( 133 | | bytes32 key, 134 | | Deposit.Props memory deposit, 135 | | EventUtils.EventLogData memory eventData 136 | | ) internal { 137 | * | if (!isValidCallbackContract(deposit.callbackContract())) { return; } 138 | | 139 | * | validateGasLeftForCallback(deposit.callbackGasLimit()); 140 | | 141 | * | try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositCancellation{ gas: deposit.callbackGasLimit() }( 142 | * | key, 143 | * | deposit, 144 | * | eventData 145 | | ) { 146 | | } catch { 147 | | emit AfterDepositCancellationError(key, deposit); 148 | | } 149 | | } 150 | | 151 | | // @dev called after a withdrawal execution 152 | | // @param key the key of the withdrawal 153 | | // @param withdrawal the withdrawal that was executed 154 | * | function afterWithdrawalExecution( 155 | | bytes32 key, 156 | | Withdrawal.Props memory withdrawal, 157 | | EventUtils.EventLogData memory eventData 158 | | ) internal { 159 | * | if (!isValidCallbackContract(withdrawal.callbackContract())) { return; } 160 | | 161 | | validateGasLeftForCallback(withdrawal.callbackGasLimit()); 162 | | 163 | | try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalExecution{ gas: withdrawal.callbackGasLimit() }( 164 | | key, 165 | | withdrawal, 166 | | eventData 167 | | ) { 168 | | } catch { 169 | | emit AfterWithdrawalExecutionError(key, withdrawal); 170 | | } 171 | | } 172 | | 173 | | // @dev called after a withdrawal cancellation 174 | | // @param key the key of the withdrawal 175 | | // @param withdrawal the withdrawal that was cancelled 176 | * | function afterWithdrawalCancellation( 177 | | bytes32 key, 178 | | Withdrawal.Props memory withdrawal, 179 | | EventUtils.EventLogData memory eventData 180 | | ) internal { 181 | * | if (!isValidCallbackContract(withdrawal.callbackContract())) { return; } 182 | | 183 | | validateGasLeftForCallback(withdrawal.callbackGasLimit()); 184 | | 185 | | try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalCancellation{ gas: withdrawal.callbackGasLimit() }( 186 | | key, 187 | | withdrawal, 188 | | eventData 189 | | ) { 190 | | } catch { 191 | | emit AfterWithdrawalCancellationError(key, withdrawal); 192 | | } 193 | | } 194 | | 195 | | function afterShiftExecution( 196 | | bytes32 key, 197 | | Shift.Props memory shift, 198 | | EventUtils.EventLogData memory eventData 199 | | ) internal { 200 | | if (!isValidCallbackContract(shift.callbackContract())) { return; } 201 | | 202 | | validateGasLeftForCallback(shift.callbackGasLimit()); 203 | | 204 | | try IShiftCallbackReceiver(shift.callbackContract()).afterShiftExecution{ gas: shift.callbackGasLimit() }( 205 | | key, 206 | | shift, 207 | | eventData 208 | | ) { 209 | | } catch { 210 | | emit AfterShiftExecutionError(key, shift); 211 | | } 212 | | } 213 | | function afterShiftCancellation( 214 | | bytes32 key, 215 | | Shift.Props memory shift, 216 | | EventUtils.EventLogData memory eventData 217 | | ) internal { 218 | | if (!isValidCallbackContract(shift.callbackContract())) { return; } 219 | | 220 | | validateGasLeftForCallback(shift.callbackGasLimit()); 221 | | 222 | | try IShiftCallbackReceiver(shift.callbackContract()).afterShiftCancellation{ gas: shift.callbackGasLimit() }( 223 | | key, 224 | | shift, 225 | | eventData 226 | | ) { 227 | | } catch { 228 | | emit AfterShiftCancellationError(key, shift); 229 | | } 230 | | } 231 | | 232 | | // @dev called after an order execution 233 | | // note that the order.size, order.initialCollateralDeltaAmount and other 234 | | // properties may be updated during execution, the new values may not be 235 | | // updated in the order object for the callback 236 | | // @param key the key of the order 237 | | // @param order the order that was executed 238 | * | function afterOrderExecution( 239 | | bytes32 key, 240 | | Order.Props memory order, 241 | | EventUtils.EventLogData memory eventData 242 | | ) internal { 243 | * | if (!isValidCallbackContract(order.callbackContract())) { return; } 244 | | 245 | * | validateGasLeftForCallback(order.callbackGasLimit()); 246 | | 247 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderExecution{ gas: order.callbackGasLimit() }( 248 | * | key, 249 | * | order, 250 | * | eventData 251 | | ) { 252 | | } catch { 253 | * | emit AfterOrderExecutionError(key, order); 254 | | } 255 | | } 256 | | 257 | | // @dev called after an order cancellation 258 | | // @param key the key of the order 259 | | // @param order the order that was cancelled 260 | * | function afterOrderCancellation( 261 | | bytes32 key, 262 | | Order.Props memory order, 263 | | EventUtils.EventLogData memory eventData 264 | | ) internal { 265 | * | if (!isValidCallbackContract(order.callbackContract())) { return; } 266 | | 267 | * | validateGasLeftForCallback(order.callbackGasLimit()); 268 | | 269 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderCancellation{ gas: order.callbackGasLimit() }( 270 | * | key, 271 | * | order, 272 | * | eventData 273 | | ) { 274 | | } catch { 275 | | emit AfterOrderCancellationError(key, order); 276 | | } 277 | | } 278 | | 279 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info 280 | | // @param key the key of the order 281 | | // @param order the order that was frozen 282 | * | function afterOrderFrozen( 283 | | bytes32 key, 284 | | Order.Props memory order, 285 | | EventUtils.EventLogData memory eventData 286 | | ) internal { 287 | * | if (!isValidCallbackContract(order.callbackContract())) { return; } 288 | | 289 | * | validateGasLeftForCallback(order.callbackGasLimit()); 290 | | 291 | * | try IOrderCallbackReceiver(order.callbackContract()).afterOrderFrozen{ gas: order.callbackGasLimit() }( 292 | * | key, 293 | * | order, 294 | * | eventData 295 | | ) { 296 | | } catch { 297 | | emit AfterOrderFrozenError(key, order); 298 | | } 299 | | } 300 | | 301 | | // @dev called after a glvDeposit execution 302 | | // @param key the key of the glvDeposit 303 | | // @param glvDeposit the glvDeposit that was executed 304 | | function afterGlvDepositExecution( 305 | | bytes32 key, 306 | | GlvDeposit.Props memory glvDeposit, 307 | | EventUtils.EventLogData memory eventData 308 | | ) internal { 309 | | if (!isValidCallbackContract(glvDeposit.callbackContract())) { return; } 310 | | 311 | | try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositExecution{ gas: glvDeposit.callbackGasLimit() }( 312 | | key, 313 | | glvDeposit, 314 | | eventData 315 | | ) { 316 | | } catch { 317 | | emit AfterGlvDepositExecutionError(key, glvDeposit); 318 | | } 319 | | } 320 | | 321 | | // @dev called after a glvDeposit cancellation 322 | | // @param key the key of the glvDeposit 323 | | // @param glvDeposit the glvDeposit that was cancelled 324 | | function afterGlvDepositCancellation( 325 | | bytes32 key, 326 | | GlvDeposit.Props memory glvDeposit, 327 | | EventUtils.EventLogData memory eventData 328 | | ) internal { 329 | | if (!isValidCallbackContract(glvDeposit.callbackContract())) { return; } 330 | | 331 | | try IGlvDepositCallbackReceiver(glvDeposit.callbackContract()).afterGlvDepositCancellation{ gas: glvDeposit.callbackGasLimit() }( 332 | | key, 333 | | glvDeposit, 334 | | eventData 335 | | ) { 336 | | } catch { 337 | | emit AfterGlvDepositCancellationError(key, glvDeposit); 338 | | } 339 | | } 340 | | 341 | | // @dev validates that the given address is a contract 342 | | // @param callbackContract the contract to call 343 | * | function isValidCallbackContract(address callbackContract) internal view returns (bool) { 344 | * | if (callbackContract == address(0)) { return false; } 345 | * | if (!callbackContract.isContract()) { return false; } 346 | | 347 | * | return true; 348 | | } 349 | | } 350 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IDepositCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | import "../deposit/Deposit.sol"; 7 | | 8 | | // @title IDepositCallbackReceiver 9 | | // @dev interface for a deposit callback contract 10 | | interface IDepositCallbackReceiver { 11 | | // @dev called after a deposit execution 12 | | // @param key the key of the deposit 13 | | // @param deposit the deposit that was executed 14 | | function afterDepositExecution(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external; 15 | | 16 | | // @dev called after a deposit cancellation 17 | | // @param key the key of the deposit 18 | | // @param deposit the deposit that was cancelled 19 | | function afterDepositCancellation(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external; 20 | | } 21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IGasFeeCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | 7 | | interface IGasFeeCallbackReceiver { 8 | | function refundExecutionFee(bytes32 key, EventUtils.EventLogData memory eventData) external payable; 9 | | } 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IGlvDepositCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | import "../glv/GlvDeposit.sol"; 7 | | 8 | | // @title IGlvDepositCallbackReceiver 9 | | // @dev interface for a glvDeposit callback contract 10 | | interface IGlvDepositCallbackReceiver { 11 | | // @dev called after a glvDeposit execution 12 | | // @param key the key of the glvDeposit 13 | | // @param glvDeposit the glvDeposit that was executed 14 | | function afterGlvDepositExecution(bytes32 key, GlvDeposit.Props memory glvDeposit, EventUtils.EventLogData memory eventData) external; 15 | | 16 | | // @dev called after a glvDeposit cancellation 17 | | // @param key the key of the glvDeposit 18 | | // @param glvDeposit the glvDeposit that was cancelled 19 | | function afterGlvDepositCancellation(bytes32 key, GlvDeposit.Props memory glvDeposit, EventUtils.EventLogData memory eventData) external; 20 | | } 21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IOrderCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | import "../order/Order.sol"; 7 | | 8 | | // @title IOrderCallbackReceiver 9 | | // @dev interface for an order callback contract 10 | | interface IOrderCallbackReceiver { 11 | | // @dev called after an order execution 12 | | // @param key the key of the order 13 | | // @param order the order that was executed 14 | | function afterOrderExecution(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external; 15 | | 16 | | // @dev called after an order cancellation 17 | | // @param key the key of the order 18 | | // @param order the order that was cancelled 19 | | function afterOrderCancellation(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external; 20 | | 21 | | // @dev called after an order has been frozen, see OrderUtils.freezeOrder in OrderHandler for more info 22 | | // @param key the key of the order 23 | | // @param order the order that was frozen 24 | | function afterOrderFrozen(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external; 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IShiftCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | import "../shift/Shift.sol"; 7 | | 8 | | interface IShiftCallbackReceiver { 9 | | function afterShiftExecution(bytes32 key, Shift.Props memory shift, EventUtils.EventLogData memory eventData) external; 10 | | function afterShiftCancellation(bytes32 key, Shift.Props memory shift, EventUtils.EventLogData memory eventData) external; 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/callback/IWithdrawalCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventUtils.sol"; 6 | | import "../withdrawal/Withdrawal.sol"; 7 | | 8 | | // @title IWithdrawalCallbackReceiver 9 | | // @dev interface for a withdrawal callback contract 10 | | interface IWithdrawalCallbackReceiver { 11 | | // @dev called after a withdrawal execution 12 | | // @param key the key of the withdrawal 13 | | // @param withdrawal the withdrawal that was executed 14 | | function afterWithdrawalExecution(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external; 15 | | 16 | | // @dev called after a withdrawal cancellation 17 | | // @param key the key of the withdrawal 18 | | // @param withdrawal the withdrawal that was cancelled 19 | | function afterWithdrawalCancellation(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external; 20 | | } 21 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/chain/ArbSys.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title ArbSys 6 | | // @dev Globally available variables for Arbitrum may have both an L1 and an L2 7 | | // value, the ArbSys interface is used to retrieve the L2 value 8 | | interface ArbSys { 9 | | function arbBlockNumber() external view returns (uint256); 10 | | function arbBlockHash(uint256 blockNumber) external view returns (bytes32); 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/chain/Chain.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./ArbSys.sol"; 6 | | 7 | | // @title Chain 8 | | // @dev Wrap the calls to retrieve chain variables to handle differences 9 | | // between chain implementations 10 | * | library Chain { 11 | | // if the ARBITRUM_CHAIN_ID changes, a new version of this library 12 | | // and contracts depending on it would need to be deployed 13 | * | uint256 internal constant ARBITRUM_CHAIN_ID = 42161; 14 | * | uint256 internal constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614; 15 | | 16 | | ArbSys internal constant arbSys = ArbSys(address(100)); 17 | | 18 | | // @dev return the current block's timestamp 19 | | // @return the current block's timestamp 20 | * | function currentTimestamp() internal view returns (uint256) { 21 | * | return block.timestamp; 22 | | } 23 | | 24 | | // @dev return the current block's number 25 | | // @return the current block's number 26 | * | function currentBlockNumber() internal view returns (uint256) { 27 | * | if (shouldUseArbSysValues()) { 28 | | return arbSys.arbBlockNumber(); 29 | | } 30 | | 31 | * | return block.number; 32 | | } 33 | | 34 | | // @dev return the current block's hash 35 | | // @return the current block's hash 36 | | function getBlockHash(uint256 blockNumber) internal view returns (bytes32) { 37 | | if (shouldUseArbSysValues()) { 38 | | return arbSys.arbBlockHash(blockNumber); 39 | | } 40 | | 41 | | return blockhash(blockNumber); 42 | | } 43 | | 44 | * | function shouldUseArbSysValues() internal view returns (bool) { 45 | * | return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID; 46 | | } 47 | | } 48 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/config/Config.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../data/Keys.sol"; 9 | | import "../role/RoleModule.sol"; 10 | | import "../event/EventEmitter.sol"; 11 | | import "../utils/BasicMulticall.sol"; 12 | | import "../utils/Precision.sol"; 13 | | import "../utils/Cast.sol"; 14 | | import "../market/MarketUtils.sol"; 15 | | 16 | | // @title Config 17 | * | contract Config is ReentrancyGuard, RoleModule, BasicMulticall { 18 | | using EventUtils for EventUtils.AddressItems; 19 | | using EventUtils for EventUtils.UintItems; 20 | | using EventUtils for EventUtils.IntItems; 21 | | using EventUtils for EventUtils.BoolItems; 22 | | using EventUtils for EventUtils.Bytes32Items; 23 | | using EventUtils for EventUtils.BytesItems; 24 | | using EventUtils for EventUtils.StringItems; 25 | | 26 | | uint256 public constant MAX_FEE_FACTOR = 5 * Precision.FLOAT_PRECISION / 100; // 5% 27 | | 28 | | DataStore public immutable dataStore; 29 | | EventEmitter public immutable eventEmitter; 30 | | 31 | | // @dev the base keys that can be set 32 | | mapping (bytes32 => bool) public allowedBaseKeys; 33 | | // @dev the limited base keys that can be set 34 | | mapping (bytes32 => bool) public allowedLimitedBaseKeys; 35 | | 36 | | constructor( 37 | | RoleStore _roleStore, 38 | | DataStore _dataStore, 39 | | EventEmitter _eventEmitter 40 | | ) RoleModule(_roleStore) { 41 | | dataStore = _dataStore; 42 | | eventEmitter = _eventEmitter; 43 | | 44 | | _initAllowedBaseKeys(); 45 | | _initAllowedLimitedBaseKeys(); 46 | | } 47 | | 48 | | modifier onlyKeeper() { 49 | | if ( 50 | | !roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER) && 51 | | !roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER) 52 | | ) { 53 | | revert Errors.Unauthorized(msg.sender, "LIMITED / CONFIG KEEPER"); 54 | | } 55 | | 56 | | _; 57 | | } 58 | | 59 | | function setFundingRate( 60 | | address market, 61 | | uint256 maxFundingFactorPerSecond 62 | | ) external onlyKeeper nonReentrant { 63 | | uint256 limit = dataStore.getUint(Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT); 64 | | 65 | | if (maxFundingFactorPerSecond > limit) { 66 | | revert Errors.MaxFundingFactorPerSecondLimitExceeded(maxFundingFactorPerSecond, limit); 67 | | } 68 | | 69 | | dataStore.setUint(Keys.maxFundingFactorPerSecondKey(market), maxFundingFactorPerSecond); 70 | | 71 | | EventUtils.EventLogData memory eventData; 72 | | eventData.addressItems.initItems(1); 73 | | eventData.addressItems.setItem(0, "market", market); 74 | | eventData.uintItems.initItems(1); 75 | | eventData.uintItems.setItem(0, "maxFundingFactorPerSecond", maxFundingFactorPerSecond); 76 | | eventEmitter.emitEventLog1( 77 | | "ConfigSetFundingRate", 78 | | Cast.toBytes32(market), 79 | | eventData 80 | | ); 81 | | } 82 | | 83 | | function setPriceFeed( 84 | | address token, 85 | | address priceFeed, 86 | | uint256 priceFeedMultiplier, 87 | | uint256 priceFeedHeartbeatDuration, 88 | | uint256 stablePrice 89 | | ) external onlyConfigKeeper nonReentrant { 90 | | if (dataStore.getAddress(Keys.priceFeedKey(token)) != address(0)) { 91 | | revert Errors.PriceFeedAlreadyExistsForToken(token); 92 | | } 93 | | 94 | | dataStore.setAddress(Keys.priceFeedKey(token), priceFeed); 95 | | dataStore.setUint(Keys.priceFeedMultiplierKey(token), priceFeedMultiplier); 96 | | dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration); 97 | | dataStore.setUint(Keys.stablePriceKey(token), stablePrice); 98 | | 99 | | EventUtils.EventLogData memory eventData; 100 | | eventData.addressItems.initItems(2); 101 | | eventData.addressItems.setItem(0, "token", token); 102 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed); 103 | | eventData.uintItems.initItems(3); 104 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier); 105 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration); 106 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice); 107 | | eventEmitter.emitEventLog1( 108 | | "ConfigSetPriceFeed", 109 | | Cast.toBytes32(token), 110 | | eventData 111 | | ); 112 | | } 113 | | 114 | | function setDataStream( 115 | | address token, 116 | | bytes32 feedId, 117 | | uint256 dataStreamMultiplier 118 | | ) external onlyTimelockAdmin nonReentrant { 119 | | if (dataStore.getBytes32(Keys.dataStreamIdKey(token)) != bytes32(0)) { 120 | | revert Errors.DataStreamIdAlreadyExistsForToken(token); 121 | | } 122 | | 123 | | dataStore.setBytes32(Keys.dataStreamIdKey(token), feedId); 124 | | dataStore.setUint(Keys.dataStreamMultiplierKey(token), dataStreamMultiplier); 125 | | 126 | | EventUtils.EventLogData memory eventData; 127 | | eventData.addressItems.initItems(1); 128 | | eventData.addressItems.setItem(0, "token", token); 129 | | eventData.bytes32Items.initItems(1); 130 | | eventData.bytes32Items.setItem(0, "feedId", feedId); 131 | | eventData.uintItems.initItems(1); 132 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier); 133 | | eventEmitter.emitEventLog1( 134 | | "ConfigSetDataStream", 135 | | Cast.toBytes32(token), 136 | | eventData 137 | | ); 138 | | } 139 | | 140 | | function setClaimableCollateralFactorForTime( 141 | | address market, 142 | | address token, 143 | | uint256 timeKey, 144 | | uint256 factor 145 | | ) external onlyConfigKeeper nonReentrant { 146 | | if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); } 147 | | 148 | | bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey); 149 | | dataStore.setUint(key, factor); 150 | | 151 | | EventUtils.EventLogData memory eventData; 152 | | 153 | | eventData.addressItems.initItems(2); 154 | | eventData.addressItems.setItem(0, "market", market); 155 | | eventData.addressItems.setItem(1, "token", token); 156 | | 157 | | eventData.uintItems.initItems(2); 158 | | eventData.uintItems.setItem(0, "timeKey", timeKey); 159 | | eventData.uintItems.setItem(1, "factor", factor); 160 | | 161 | | eventEmitter.emitEventLog2( 162 | | "SetClaimableCollateralFactorForTime", 163 | | Cast.toBytes32(market), 164 | | Cast.toBytes32(token), 165 | | eventData 166 | | ); 167 | | } 168 | | 169 | | function setClaimableCollateralFactorForAccount( 170 | | address market, 171 | | address token, 172 | | uint256 timeKey, 173 | | address account, 174 | | uint256 factor 175 | | ) external onlyConfigKeeper nonReentrant { 176 | | if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); } 177 | | 178 | | bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey, account); 179 | | dataStore.setUint(key, factor); 180 | | 181 | | EventUtils.EventLogData memory eventData; 182 | | 183 | | eventData.addressItems.initItems(3); 184 | | eventData.addressItems.setItem(0, "market", market); 185 | | eventData.addressItems.setItem(1, "token", token); 186 | | eventData.addressItems.setItem(2, "account", account); 187 | | 188 | | eventData.uintItems.initItems(2); 189 | | eventData.uintItems.setItem(0, "timeKey", timeKey); 190 | | eventData.uintItems.setItem(1, "factor", factor); 191 | | 192 | | eventEmitter.emitEventLog2( 193 | | "SetClaimableCollateralFactorForAccount", 194 | | Cast.toBytes32(market), 195 | | Cast.toBytes32(token), 196 | | eventData 197 | | ); 198 | | } 199 | | 200 | | function setPositionImpactDistributionRate( 201 | | address market, 202 | | uint256 minPositionImpactPoolAmount, 203 | | uint256 positionImpactPoolDistributionRate 204 | | ) external onlyConfigKeeper nonReentrant { 205 | | MarketUtils.distributePositionImpactPool(dataStore, eventEmitter, market); 206 | | 207 | | dataStore.setUint(Keys.minPositionImpactPoolAmountKey(market), minPositionImpactPoolAmount); 208 | | dataStore.setUint(Keys.positionImpactPoolDistributionRateKey(market), positionImpactPoolDistributionRate); 209 | | 210 | | dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp()); 211 | | 212 | | EventUtils.EventLogData memory eventData; 213 | | 214 | | eventData.addressItems.initItems(1); 215 | | eventData.addressItems.setItem(0, "market", market); 216 | | 217 | | eventData.uintItems.initItems(2); 218 | | eventData.uintItems.setItem(0, "minPositionImpactPoolAmount", minPositionImpactPoolAmount); 219 | | eventData.uintItems.setItem(1, "positionImpactPoolDistributionRate", positionImpactPoolDistributionRate); 220 | | 221 | | eventEmitter.emitEventLog1( 222 | | "SetPositionImpactPoolDistributionRate", 223 | | Cast.toBytes32(market), 224 | | eventData 225 | | ); 226 | | } 227 | | 228 | | // @dev set a bool value 229 | | // @param baseKey the base key of the value to set 230 | | // @param data the additional data to be combined with the base key 231 | | // @param value the bool value 232 | | function setBool(bytes32 baseKey, bytes memory data, bool value) external onlyKeeper nonReentrant { 233 | | _validateKey(baseKey); 234 | | 235 | | bytes32 fullKey = _getFullKey(baseKey, data); 236 | | 237 | | dataStore.setBool(fullKey, value); 238 | | 239 | | EventUtils.EventLogData memory eventData; 240 | | 241 | | eventData.bytes32Items.initItems(1); 242 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey); 243 | | 244 | | eventData.bytesItems.initItems(1); 245 | | eventData.bytesItems.setItem(0, "data", data); 246 | | 247 | | eventData.boolItems.initItems(1); 248 | | eventData.boolItems.setItem(0, "value", value); 249 | | 250 | | eventEmitter.emitEventLog1( 251 | | "SetBool", 252 | | baseKey, 253 | | eventData 254 | | ); 255 | | } 256 | | 257 | | // @dev set an address value 258 | | // @param baseKey the base key of the value to set 259 | | // @param data the additional data to be combined with the base key 260 | | // @param value the address value 261 | | function setAddress(bytes32 baseKey, bytes memory data, address value) external onlyKeeper nonReentrant { 262 | | _validateKey(baseKey); 263 | | 264 | | bytes32 fullKey = _getFullKey(baseKey, data); 265 | | 266 | | dataStore.setAddress(fullKey, value); 267 | | 268 | | EventUtils.EventLogData memory eventData; 269 | | 270 | | eventData.bytes32Items.initItems(1); 271 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey); 272 | | 273 | | eventData.bytesItems.initItems(1); 274 | | eventData.bytesItems.setItem(0, "data", data); 275 | | 276 | | eventData.addressItems.initItems(1); 277 | | eventData.addressItems.setItem(0, "value", value); 278 | | 279 | | eventEmitter.emitEventLog1( 280 | | "SetAddress", 281 | | baseKey, 282 | | eventData 283 | | ); 284 | | } 285 | | 286 | | // @dev set a bytes32 value 287 | | // @param baseKey the base key of the value to set 288 | | // @param data the additional data to be combined with the base key 289 | | // @param value the bytes32 value 290 | | function setBytes32(bytes32 baseKey, bytes memory data, bytes32 value) external onlyKeeper nonReentrant { 291 | | _validateKey(baseKey); 292 | | 293 | | bytes32 fullKey = _getFullKey(baseKey, data); 294 | | 295 | | dataStore.setBytes32(fullKey, value); 296 | | 297 | | EventUtils.EventLogData memory eventData; 298 | | 299 | | eventData.bytes32Items.initItems(2); 300 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey); 301 | | eventData.bytes32Items.setItem(1, "value", value); 302 | | 303 | | eventData.bytesItems.initItems(1); 304 | | eventData.bytesItems.setItem(0, "data", data); 305 | | 306 | | eventEmitter.emitEventLog1( 307 | | "SetBytes32", 308 | | baseKey, 309 | | eventData 310 | | ); 311 | | } 312 | | 313 | | // @dev set a uint256 value 314 | | // @param basekey the base key of the value to set 315 | | // @param data the additional data to be combined with the base key 316 | | // @param value the uint256 value 317 | | function setUint(bytes32 baseKey, bytes memory data, uint256 value) external onlyKeeper nonReentrant { 318 | | _validateKey(baseKey); 319 | | 320 | | bytes32 fullKey = _getFullKey(baseKey, data); 321 | | 322 | | _validateRange(baseKey, value); 323 | | 324 | | dataStore.setUint(fullKey, value); 325 | | 326 | | EventUtils.EventLogData memory eventData; 327 | | 328 | | eventData.bytes32Items.initItems(1); 329 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey); 330 | | 331 | | eventData.bytesItems.initItems(1); 332 | | eventData.bytesItems.setItem(0, "data", data); 333 | | 334 | | eventData.uintItems.initItems(1); 335 | | eventData.uintItems.setItem(0, "value", value); 336 | | 337 | | eventEmitter.emitEventLog1( 338 | | "SetUint", 339 | | baseKey, 340 | | eventData 341 | | ); 342 | | } 343 | | 344 | | // @dev set an int256 value 345 | | // @param basekey the base key of the value to set 346 | | // @param data the additional data to be combined with the base key 347 | | // @param value the int256 value 348 | | function setInt(bytes32 baseKey, bytes memory data, int256 value) external onlyKeeper nonReentrant { 349 | | _validateKey(baseKey); 350 | | 351 | | bytes32 fullKey = _getFullKey(baseKey, data); 352 | | 353 | | dataStore.setInt(fullKey, value); 354 | | 355 | | EventUtils.EventLogData memory eventData; 356 | | 357 | | eventData.bytes32Items.initItems(1); 358 | | eventData.bytes32Items.setItem(0, "baseKey", baseKey); 359 | | 360 | | eventData.bytesItems.initItems(1); 361 | | eventData.bytesItems.setItem(0, "data", data); 362 | | 363 | | eventData.intItems.initItems(1); 364 | | eventData.intItems.setItem(0, "value", value); 365 | | 366 | | eventEmitter.emitEventLog1( 367 | | "SetInt", 368 | | baseKey, 369 | | eventData 370 | | ); 371 | | } 372 | | 373 | | function _getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) { 374 | | if (data.length == 0) { 375 | | return baseKey; 376 | | } 377 | | 378 | | return keccak256(bytes.concat(baseKey, data)); 379 | | } 380 | | 381 | | // @dev initialize the allowed base keys 382 | | function _initAllowedBaseKeys() internal { 383 | | allowedBaseKeys[Keys.HOLDING_ADDRESS] = true; 384 | | 385 | | allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS] = true; 386 | | allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD] = true; 387 | | allowedBaseKeys[Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION] = true; 388 | | 389 | | allowedBaseKeys[Keys.IS_MARKET_DISABLED] = true; 390 | | 391 | | allowedBaseKeys[Keys.MAX_SWAP_PATH_LENGTH] = true; 392 | | allowedBaseKeys[Keys.MAX_CALLBACK_GAS_LIMIT] = true; 393 | | allowedBaseKeys[Keys.REFUND_EXECUTION_FEE_GAS_LIMIT] = true; 394 | | 395 | | allowedBaseKeys[Keys.MIN_POSITION_SIZE_USD] = true; 396 | | allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS] = true; 397 | | 398 | | allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true; 399 | | allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true; 400 | | allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true; 401 | | 402 | | allowedBaseKeys[Keys.MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT] = true; 403 | | 404 | | allowedBaseKeys[Keys.CREATE_DEPOSIT_FEATURE_DISABLED] = true; 405 | | allowedBaseKeys[Keys.CANCEL_DEPOSIT_FEATURE_DISABLED] = true; 406 | | allowedBaseKeys[Keys.EXECUTE_DEPOSIT_FEATURE_DISABLED] = true; 407 | | 408 | | allowedBaseKeys[Keys.GLV_SHIFT_FEATURE_DISABLED] = true; 409 | | 410 | | allowedBaseKeys[Keys.CREATE_WITHDRAWAL_FEATURE_DISABLED] = true; 411 | | allowedBaseKeys[Keys.CANCEL_WITHDRAWAL_FEATURE_DISABLED] = true; 412 | | allowedBaseKeys[Keys.EXECUTE_WITHDRAWAL_FEATURE_DISABLED] = true; 413 | | allowedBaseKeys[Keys.EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED] = true; 414 | | 415 | | allowedBaseKeys[Keys.CREATE_SHIFT_FEATURE_DISABLED] = true; 416 | | allowedBaseKeys[Keys.CANCEL_SHIFT_FEATURE_DISABLED] = true; 417 | | allowedBaseKeys[Keys.EXECUTE_SHIFT_FEATURE_DISABLED] = true; 418 | | 419 | | allowedBaseKeys[Keys.CREATE_ORDER_FEATURE_DISABLED] = true; 420 | | allowedBaseKeys[Keys.EXECUTE_ORDER_FEATURE_DISABLED] = true; 421 | | allowedBaseKeys[Keys.EXECUTE_ADL_FEATURE_DISABLED] = true; 422 | | allowedBaseKeys[Keys.UPDATE_ORDER_FEATURE_DISABLED] = true; 423 | | allowedBaseKeys[Keys.CANCEL_ORDER_FEATURE_DISABLED] = true; 424 | | 425 | | allowedBaseKeys[Keys.CREATE_GLV_DEPOSIT_FEATURE_DISABLED] = true; 426 | | allowedBaseKeys[Keys.CANCEL_GLV_DEPOSIT_FEATURE_DISABLED] = true; 427 | | allowedBaseKeys[Keys.EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED] = true; 428 | | 429 | | allowedBaseKeys[Keys.CLAIM_FUNDING_FEES_FEATURE_DISABLED] = true; 430 | | allowedBaseKeys[Keys.CLAIM_COLLATERAL_FEATURE_DISABLED] = true; 431 | | allowedBaseKeys[Keys.CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED] = true; 432 | | allowedBaseKeys[Keys.CLAIM_UI_FEES_FEATURE_DISABLED] = true; 433 | | 434 | | allowedBaseKeys[Keys.SUBACCOUNT_FEATURE_DISABLED] = true; 435 | | 436 | | allowedBaseKeys[Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS] = true; 437 | | allowedBaseKeys[Keys.MAX_ORACLE_PRICE_AGE] = true; 438 | | allowedBaseKeys[Keys.MAX_ORACLE_TIMESTAMP_RANGE] = true; 439 | | allowedBaseKeys[Keys.ORACLE_TIMESTAMP_ADJUSTMENT] = true; 440 | | allowedBaseKeys[Keys.ORACLE_PROVIDER_FOR_TOKEN] = true; 441 | | allowedBaseKeys[Keys.CHAINLINK_PAYMENT_TOKEN] = true; 442 | | allowedBaseKeys[Keys.SEQUENCER_GRACE_DURATION] = true; 443 | | allowedBaseKeys[Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR] = true; 444 | | 445 | | allowedBaseKeys[Keys.POSITION_FEE_RECEIVER_FACTOR] = true; 446 | | allowedBaseKeys[Keys.SWAP_FEE_RECEIVER_FACTOR] = true; 447 | | allowedBaseKeys[Keys.BORROWING_FEE_RECEIVER_FACTOR] = true; 448 | | 449 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true; 450 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true; 451 | | allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true; 452 | | 453 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true; 454 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true; 455 | | allowedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true; 456 | | 457 | | allowedBaseKeys[Keys.DEPOSIT_GAS_LIMIT] = true; 458 | | allowedBaseKeys[Keys.GLV_DEPOSIT_GAS_LIMIT] = true; 459 | | allowedBaseKeys[Keys.GLV_PER_MARKET_GAS_LIMIT] = true; 460 | | allowedBaseKeys[Keys.WITHDRAWAL_GAS_LIMIT] = true; 461 | | allowedBaseKeys[Keys.SHIFT_GAS_LIMIT] = true; 462 | | allowedBaseKeys[Keys.SINGLE_SWAP_GAS_LIMIT] = true; 463 | | allowedBaseKeys[Keys.INCREASE_ORDER_GAS_LIMIT] = true; 464 | | allowedBaseKeys[Keys.DECREASE_ORDER_GAS_LIMIT] = true; 465 | | allowedBaseKeys[Keys.SWAP_ORDER_GAS_LIMIT] = true; 466 | | allowedBaseKeys[Keys.TOKEN_TRANSFER_GAS_LIMIT] = true; 467 | | allowedBaseKeys[Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT] = true; 468 | | 469 | | allowedBaseKeys[Keys.REQUEST_EXPIRATION_TIME] = true; 470 | | allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR] = true; 471 | | allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER] = true; 472 | | allowedBaseKeys[Keys.MIN_COLLATERAL_USD] = true; 473 | | 474 | | allowedBaseKeys[Keys.VIRTUAL_TOKEN_ID] = true; 475 | | allowedBaseKeys[Keys.VIRTUAL_MARKET_ID] = true; 476 | | allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_SWAPS] = true; 477 | | allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_POSITIONS] = true; 478 | | 479 | | allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true; 480 | | allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true; 481 | | allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR] = true; 482 | | allowedBaseKeys[Keys.POSITION_FEE_FACTOR] = true; 483 | | 484 | | allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true; 485 | | allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true; 486 | | allowedBaseKeys[Keys.SWAP_FEE_FACTOR] = true; 487 | | allowedBaseKeys[Keys.ATOMIC_SWAP_FEE_FACTOR] = true; 488 | | 489 | | allowedBaseKeys[Keys.MAX_UI_FEE_FACTOR] = true; 490 | | allowedBaseKeys[Keys.MAX_AUTO_CANCEL_ORDERS] = true; 491 | | allowedBaseKeys[Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS] = true; 492 | | 493 | | allowedBaseKeys[Keys.ORACLE_TYPE] = true; 494 | | 495 | | allowedBaseKeys[Keys.RESERVE_FACTOR] = true; 496 | | allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true; 497 | | 498 | | allowedBaseKeys[Keys.MAX_PNL_FACTOR] = true; 499 | | allowedBaseKeys[Keys.MIN_PNL_FACTOR_AFTER_ADL] = true; 500 | | 501 | | allowedBaseKeys[Keys.FUNDING_FACTOR] = true; 502 | | allowedBaseKeys[Keys.FUNDING_EXPONENT_FACTOR] = true; 503 | | allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true; 504 | | allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true; 505 | | allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true; 506 | | allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true; 507 | | allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT] = true; 508 | | allowedBaseKeys[Keys.THRESHOLD_FOR_STABLE_FUNDING] = true; 509 | | allowedBaseKeys[Keys.THRESHOLD_FOR_DECREASE_FUNDING] = true; 510 | | 511 | | allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true; 512 | | allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true; 513 | | allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true; 514 | | allowedBaseKeys[Keys.BORROWING_FACTOR] = true; 515 | | allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true; 516 | | allowedBaseKeys[Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE] = true; 517 | | 518 | | allowedBaseKeys[Keys.PRICE_FEED_HEARTBEAT_DURATION] = true; 519 | | 520 | | allowedBaseKeys[Keys.IS_GLV_MARKET_DISABLED] = true; 521 | | allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true; 522 | | } 523 | | 524 | | function _initAllowedLimitedBaseKeys() internal { 525 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true; 526 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true; 527 | | allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true; 528 | | 529 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true; 530 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true; 531 | | allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true; 532 | | 533 | | allowedLimitedBaseKeys[Keys.MAX_POOL_AMOUNT] = true; 534 | | allowedLimitedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true; 535 | | allowedLimitedBaseKeys[Keys.MAX_OPEN_INTEREST] = true; 536 | | } 537 | | 538 | | // @dev validate that the baseKey is allowed to be used 539 | | // @param baseKey the base key to validate 540 | | function _validateKey(bytes32 baseKey) internal view { 541 | | if (roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)) { 542 | | if (!allowedBaseKeys[baseKey]) { 543 | | revert Errors.InvalidBaseKey(baseKey); 544 | | } 545 | | 546 | | return; 547 | | } 548 | | 549 | | if (roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER)) { 550 | | if (!allowedLimitedBaseKeys[baseKey]) { 551 | | revert Errors.InvalidBaseKey(baseKey); 552 | | } 553 | | 554 | | return; 555 | | } 556 | | 557 | | revert Errors.InvalidBaseKey(baseKey); 558 | | } 559 | | 560 | | // @dev validate that the value is within the allowed range 561 | | // @param baseKey the base key for the value 562 | | // @param value the value to be set 563 | | function _validateRange(bytes32 baseKey, uint256 value) internal pure { 564 | | if ( 565 | | baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND || 566 | | baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND_LIMIT 567 | | ) { 568 | | // 0.00001% per second, ~315% per year 569 | | if (value > 100000000000000000000000) { 570 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 571 | | } 572 | | } 573 | | 574 | | if ( 575 | | baseKey == Keys.BORROWING_FACTOR || 576 | | baseKey == Keys.BASE_BORROWING_FACTOR || 577 | | baseKey == Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR 578 | | ) { 579 | | // 0.000005% per second, ~157% per year at 100% utilization 580 | | if (value > 50000000000000000000000) { 581 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 582 | | } 583 | | } 584 | | 585 | | if ( 586 | | baseKey == Keys.FUNDING_EXPONENT_FACTOR || 587 | | baseKey == Keys.BORROWING_EXPONENT_FACTOR 588 | | ) { 589 | | // revert if value > 2 590 | | if (value > 2 * Precision.FLOAT_PRECISION) { 591 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 592 | | } 593 | | } 594 | | 595 | | if ( 596 | | baseKey == Keys.POSITION_IMPACT_EXPONENT_FACTOR || 597 | | baseKey == Keys.SWAP_IMPACT_EXPONENT_FACTOR 598 | | ) { 599 | | // revert if value > 3 600 | | if (value > 3 * Precision.FLOAT_PRECISION) { 601 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 602 | | } 603 | | } 604 | | 605 | | if ( 606 | | baseKey == Keys.FUNDING_FACTOR || 607 | | baseKey == Keys.BORROWING_FACTOR || 608 | | baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND || 609 | | baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND || 610 | | baseKey == Keys.MIN_COLLATERAL_FACTOR 611 | | ) { 612 | | // revert if value > 1% 613 | | if (value > 1 * Precision.FLOAT_PRECISION / 100) { 614 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 615 | | } 616 | | } 617 | | 618 | | if ( 619 | | baseKey == Keys.SWAP_FEE_FACTOR || 620 | | baseKey == Keys.POSITION_FEE_FACTOR || 621 | | baseKey == Keys.MAX_UI_FEE_FACTOR || 622 | | baseKey == Keys.ATOMIC_SWAP_FEE_FACTOR 623 | | ) { 624 | | // revert if value > 5% 625 | | if (value > 5 * Precision.FLOAT_PRECISION / 100) { 626 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 627 | | } 628 | | } 629 | | 630 | | if ( 631 | | baseKey == Keys.POSITION_FEE_RECEIVER_FACTOR || 632 | | baseKey == Keys.SWAP_FEE_RECEIVER_FACTOR || 633 | | baseKey == Keys.BORROWING_FEE_RECEIVER_FACTOR || 634 | | baseKey == Keys.MAX_PNL_FACTOR || 635 | | baseKey == Keys.MIN_PNL_FACTOR_AFTER_ADL || 636 | | baseKey == Keys.OPTIMAL_USAGE_FACTOR 637 | | ) { 638 | | // revert if value > 100% 639 | | if (value > Precision.FLOAT_PRECISION) { 640 | | revert Errors.ConfigValueExceedsAllowedRange(baseKey, value); 641 | | } 642 | | } 643 | | } 644 | | } 645 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/config/Timelock.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | | 7 | | import "../role/RoleModule.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | import "../utils/BasicMulticall.sol"; 10 | | import "../oracle/OracleStore.sol"; 11 | | import "../data/DataStore.sol"; 12 | | import "../data/Keys.sol"; 13 | | import "../chain/Chain.sol"; 14 | | 15 | | // @title Timelock 16 | * | contract Timelock is ReentrancyGuard, RoleModule, BasicMulticall { 17 | | using EventUtils for EventUtils.AddressItems; 18 | | using EventUtils for EventUtils.UintItems; 19 | | using EventUtils for EventUtils.IntItems; 20 | | using EventUtils for EventUtils.BoolItems; 21 | | using EventUtils for EventUtils.Bytes32Items; 22 | | using EventUtils for EventUtils.BytesItems; 23 | | using EventUtils for EventUtils.StringItems; 24 | | 25 | | using EnumerableSet for EnumerableSet.Bytes32Set; 26 | | using EnumerableValues for EnumerableSet.Bytes32Set; 27 | | 28 | | uint256 public constant MAX_TIMELOCK_DELAY = 5 days; 29 | | 30 | | DataStore public immutable dataStore; 31 | | EventEmitter public immutable eventEmitter; 32 | | OracleStore public immutable oracleStore; 33 | | uint256 public timelockDelay; 34 | | 35 | | mapping (bytes32 => uint256) public pendingActions; 36 | | EnumerableSet.Bytes32Set internal pendingActionsList; 37 | | 38 | | constructor( 39 | | RoleStore _roleStore, 40 | | DataStore _dataStore, 41 | | EventEmitter _eventEmitter, 42 | | OracleStore _oracleStore, 43 | | uint256 _timelockDelay 44 | | ) RoleModule(_roleStore) { 45 | | dataStore = _dataStore; 46 | | eventEmitter = _eventEmitter; 47 | | oracleStore = _oracleStore; 48 | | timelockDelay = _timelockDelay; 49 | | 50 | | _validateTimelockDelay(); 51 | | } 52 | | 53 | | function getPendingActionsCount() internal view returns (uint256) { 54 | | return pendingActionsList.length(); 55 | | } 56 | | 57 | | function getPendingActionsList(uint256 start, uint256 end) internal view returns (bytes32[] memory) { 58 | | return pendingActionsList.valuesAt(start, end); 59 | | } 60 | | 61 | | // @dev immediately revoke the role of an account 62 | | // @param account the account to revoke the role for 63 | | // @param roleKey the role to revoke 64 | | function revokeRole(address account, bytes32 roleKey) external onlyTimelockMultisig nonReentrant { 65 | | roleStore.revokeRole(account, roleKey); 66 | | 67 | | EventUtils.EventLogData memory eventData; 68 | | eventData.addressItems.initItems(1); 69 | | eventData.addressItems.setItem(0, "account", account); 70 | | eventData.bytes32Items.initItems(1); 71 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey); 72 | | eventEmitter.emitEventLog( 73 | | "RevokeRole", 74 | | eventData 75 | | ); 76 | | } 77 | | 78 | | // @dev increase the timelock delay 79 | | // @param the new timelock delay 80 | | function increaseTimelockDelay(uint256 _timelockDelay) external onlyTimelockAdmin nonReentrant { 81 | | if (_timelockDelay <= timelockDelay) { 82 | | revert Errors.InvalidTimelockDelay(_timelockDelay); 83 | | } 84 | | 85 | | timelockDelay = _timelockDelay; 86 | | 87 | | _validateTimelockDelay(); 88 | | 89 | | EventUtils.EventLogData memory eventData; 90 | | eventData.uintItems.initItems(1); 91 | | eventData.uintItems.setItem(0, "_timelockDelay", _timelockDelay); 92 | | eventEmitter.emitEventLog( 93 | | "IncreaseTimelockDelay", 94 | | eventData 95 | | ); 96 | | } 97 | | 98 | | function setOracleProviderEnabled(address provider, bool value) external onlyTimelockMultisig nonReentrant { 99 | | dataStore.setBool(Keys.isOracleProviderEnabledKey(provider), value); 100 | | 101 | | EventUtils.EventLogData memory eventData; 102 | | eventData.addressItems.initItems(1); 103 | | eventData.addressItems.setItem(0, "provider", provider); 104 | | eventData.boolItems.initItems(1); 105 | | eventData.boolItems.setItem(0, "value", value); 106 | | eventEmitter.emitEventLog( 107 | | "SetOracleProviderEnabled", 108 | | eventData 109 | | ); 110 | | } 111 | | 112 | | function signalSetOracleProviderEnabled(address provider, bool value) external onlyTimelockAdmin nonReentrant { 113 | | bytes32 actionKey = _setOracleProviderEnabledKey(provider, value); 114 | | _signalPendingAction(actionKey, "setOracleProviderEnabled"); 115 | | 116 | | EventUtils.EventLogData memory eventData; 117 | | eventData.addressItems.initItems(1); 118 | | eventData.addressItems.setItem(0, "provider", provider); 119 | | eventData.boolItems.initItems(1); 120 | | eventData.boolItems.setItem(0, "value", value); 121 | | eventEmitter.emitEventLog( 122 | | "SignalSetOracleProviderEnabled", 123 | | eventData 124 | | ); 125 | | } 126 | | 127 | | function setOracleProviderEnabledAfterSignal(address provider, bool value) external onlyTimelockAdmin nonReentrant { 128 | | bytes32 actionKey = _setOracleProviderEnabledKey(provider, value); 129 | | _validateAndClearAction(actionKey, "setOracleProviderEnabled"); 130 | | 131 | | dataStore.setBool(Keys.isOracleProviderEnabledKey(provider), value); 132 | | 133 | | EventUtils.EventLogData memory eventData; 134 | | eventData.addressItems.initItems(1); 135 | | eventData.addressItems.setItem(0, "provider", provider); 136 | | eventData.boolItems.initItems(1); 137 | | eventData.boolItems.setItem(0, "value", value); 138 | | eventEmitter.emitEventLog( 139 | | "SetOracleProviderEnabled", 140 | | eventData 141 | | ); 142 | | } 143 | | 144 | | function signalSetAtomicOracleProvider(address provider, bool value) external onlyTimelockAdmin nonReentrant { 145 | | bytes32 actionKey = _setAtomicOracleProviderKey(provider, value); 146 | | _signalPendingAction(actionKey, "setAtomicOracleProvider"); 147 | | 148 | | EventUtils.EventLogData memory eventData; 149 | | eventData.addressItems.initItems(1); 150 | | eventData.addressItems.setItem(0, "provider", provider); 151 | | eventData.boolItems.initItems(1); 152 | | eventData.boolItems.setItem(0, "value", value); 153 | | eventEmitter.emitEventLog( 154 | | "SignalSetAtomicOracleProvider", 155 | | eventData 156 | | ); 157 | | } 158 | | 159 | | function setAtomicOracleProviderAfterSignal(address provider, bool value) external onlyTimelockAdmin nonReentrant { 160 | | bytes32 actionKey = _setAtomicOracleProviderKey(provider, value); 161 | | _validateAndClearAction(actionKey, "setAtomicOracleProvider"); 162 | | 163 | | dataStore.setBool(Keys.isAtomicOracleProviderKey(provider), value); 164 | | 165 | | EventUtils.EventLogData memory eventData; 166 | | eventData.addressItems.initItems(1); 167 | | eventData.addressItems.setItem(0, "provider", provider); 168 | | eventData.boolItems.initItems(1); 169 | | eventData.boolItems.setItem(0, "value", value); 170 | | eventEmitter.emitEventLog( 171 | | "SetAtomicOracleProvider", 172 | | eventData 173 | | ); 174 | | } 175 | | 176 | | function signalAddOracleSigner(address account) external onlyTimelockAdmin nonReentrant { 177 | | if (account == address(0)) { 178 | | revert Errors.InvalidOracleSigner(account); 179 | | } 180 | | 181 | | bytes32 actionKey = _addOracleSignerActionKey(account); 182 | | _signalPendingAction(actionKey, "addOracleSigner"); 183 | | 184 | | EventUtils.EventLogData memory eventData; 185 | | eventData.addressItems.initItems(1); 186 | | eventData.addressItems.setItem(0, "account", account); 187 | | eventEmitter.emitEventLog1( 188 | | "SignalAddOracleSigner", 189 | | actionKey, 190 | | eventData 191 | | ); 192 | | } 193 | | 194 | | function addOracleSignerAfterSignal(address account) external onlyTimelockAdmin nonReentrant { 195 | | bytes32 actionKey = _addOracleSignerActionKey(account); 196 | | _validateAndClearAction(actionKey, "addOracleSigner"); 197 | | 198 | | oracleStore.addSigner(account); 199 | | 200 | | EventUtils.EventLogData memory eventData; 201 | | eventData.addressItems.initItems(1); 202 | | eventData.addressItems.setItem(0, "account", account); 203 | | eventEmitter.emitEventLog1( 204 | | "AddOracleSigner", 205 | | actionKey, 206 | | eventData 207 | | ); 208 | | } 209 | | 210 | | function signalRemoveOracleSigner(address account) external onlyTimelockAdmin nonReentrant { 211 | | if (account == address(0)) { 212 | | revert Errors.InvalidOracleSigner(account); 213 | | } 214 | | 215 | | bytes32 actionKey = _removeOracleSignerActionKey(account); 216 | | _signalPendingAction(actionKey, "removeOracleSigner"); 217 | | 218 | | EventUtils.EventLogData memory eventData; 219 | | eventData.addressItems.initItems(1); 220 | | eventData.addressItems.setItem(0, "account", account); 221 | | eventEmitter.emitEventLog1( 222 | | "SignalRemoveOracleSigner", 223 | | actionKey, 224 | | eventData 225 | | ); 226 | | } 227 | | 228 | | function removeOracleSignerAfterSignal(address account) external onlyTimelockAdmin nonReentrant { 229 | | bytes32 actionKey = _removeOracleSignerActionKey(account); 230 | | _validateAndClearAction(actionKey, "removeOracleSigner"); 231 | | 232 | | oracleStore.removeSigner(account); 233 | | 234 | | EventUtils.EventLogData memory eventData; 235 | | eventData.addressItems.initItems(1); 236 | | eventData.addressItems.setItem(0, "account", account); 237 | | eventEmitter.emitEventLog1( 238 | | "RemoveOracleSigner", 239 | | actionKey, 240 | | eventData 241 | | ); 242 | | } 243 | | 244 | | // @dev signal setting of the fee receiver 245 | | // @param account the new fee receiver 246 | | function signalSetFeeReceiver(address account) external onlyTimelockAdmin nonReentrant { 247 | | if (account == address(0)) { 248 | | revert Errors.InvalidFeeReceiver(account); 249 | | } 250 | | 251 | | bytes32 actionKey = _setFeeReceiverActionKey(account); 252 | | _signalPendingAction(actionKey, "setFeeReceiver"); 253 | | 254 | | EventUtils.EventLogData memory eventData; 255 | | eventData.addressItems.initItems(1); 256 | | eventData.addressItems.setItem(0, "account", account); 257 | | eventEmitter.emitEventLog1( 258 | | "SignalSetFeeReceiver", 259 | | actionKey, 260 | | eventData 261 | | ); 262 | | } 263 | | 264 | | // @dev set the fee receiver 265 | | // @param account the new fee receiver 266 | | function setFeeReceiverAfterSignal(address account) external onlyTimelockAdmin nonReentrant { 267 | | bytes32 actionKey = _setFeeReceiverActionKey(account); 268 | | _validateAndClearAction(actionKey, "setFeeReceiver"); 269 | | 270 | | dataStore.setAddress(Keys.FEE_RECEIVER, account); 271 | | 272 | | EventUtils.EventLogData memory eventData; 273 | | eventData.addressItems.initItems(1); 274 | | eventData.addressItems.setItem(0, "account", account); 275 | | eventEmitter.emitEventLog1( 276 | | "SetFeeReceiver", 277 | | actionKey, 278 | | eventData 279 | | ); 280 | | } 281 | | 282 | | // @dev signal granting of a role 283 | | // @param account the account to grant the role 284 | | // @param roleKey the role to grant 285 | | function signalGrantRole(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant { 286 | | bytes32 actionKey = _grantRoleActionKey(account, roleKey); 287 | | _signalPendingAction(actionKey, "grantRole"); 288 | | 289 | | EventUtils.EventLogData memory eventData; 290 | | eventData.addressItems.initItems(1); 291 | | eventData.addressItems.setItem(0, "account", account); 292 | | eventData.bytes32Items.initItems(1); 293 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey); 294 | | eventEmitter.emitEventLog1( 295 | | "SignalGrantRole", 296 | | actionKey, 297 | | eventData 298 | | ); 299 | | } 300 | | 301 | | // @dev grant a role 302 | | // @param account the account to grant the role 303 | | // @param roleKey the role to grant 304 | | function grantRoleAfterSignal(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant { 305 | | bytes32 actionKey = _grantRoleActionKey(account, roleKey); 306 | | _validateAndClearAction(actionKey, "grantRole"); 307 | | 308 | | roleStore.grantRole(account, roleKey); 309 | | 310 | | EventUtils.EventLogData memory eventData; 311 | | eventData.addressItems.initItems(1); 312 | | eventData.addressItems.setItem(0, "account", account); 313 | | eventData.bytes32Items.initItems(1); 314 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey); 315 | | eventEmitter.emitEventLog1( 316 | | "GrantRole", 317 | | actionKey, 318 | | eventData 319 | | ); 320 | | } 321 | | 322 | | // @dev signal revoking of a role 323 | | // @param account the account to revoke the role for 324 | | // @param roleKey the role to revoke 325 | | function signalRevokeRole(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant { 326 | | bytes32 actionKey = _revokeRoleActionKey(account, roleKey); 327 | | _signalPendingAction(actionKey, "revokeRole"); 328 | | 329 | | EventUtils.EventLogData memory eventData; 330 | | eventData.addressItems.initItems(1); 331 | | eventData.addressItems.setItem(0, "account", account); 332 | | eventData.bytes32Items.initItems(1); 333 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey); 334 | | eventEmitter.emitEventLog1( 335 | | "SignalRevokeRole", 336 | | actionKey, 337 | | eventData 338 | | ); 339 | | } 340 | | 341 | | // @dev revoke a role 342 | | // @param account the account to revoke the role for 343 | | // @param roleKey the role to revoke 344 | | function revokeRoleAfterSignal(address account, bytes32 roleKey) external onlyTimelockAdmin nonReentrant { 345 | | bytes32 actionKey = _revokeRoleActionKey(account, roleKey); 346 | | _validateAndClearAction(actionKey, "revokeRole"); 347 | | 348 | | roleStore.revokeRole(account, roleKey); 349 | | 350 | | EventUtils.EventLogData memory eventData; 351 | | eventData.addressItems.initItems(1); 352 | | eventData.addressItems.setItem(0, "account", account); 353 | | eventData.bytes32Items.initItems(1); 354 | | eventData.bytes32Items.setItem(0, "roleKey", roleKey); 355 | | eventEmitter.emitEventLog1( 356 | | "RevokeRole", 357 | | actionKey, 358 | | eventData 359 | | ); 360 | | } 361 | | 362 | | // @dev signal setting of a price feed 363 | | // @param token the token to set the price feed for 364 | | // @param priceFeed the address of the price feed 365 | | // @param priceFeedMultiplier the multiplier to apply to the price feed results 366 | | // @param stablePrice the stable price to set a range for the price feed results 367 | | function signalSetPriceFeed( 368 | | address token, 369 | | address priceFeed, 370 | | uint256 priceFeedMultiplier, 371 | | uint256 priceFeedHeartbeatDuration, 372 | | uint256 stablePrice 373 | | ) external onlyTimelockAdmin nonReentrant { 374 | | bytes32 actionKey = _setPriceFeedActionKey( 375 | | token, 376 | | priceFeed, 377 | | priceFeedMultiplier, 378 | | priceFeedHeartbeatDuration, 379 | | stablePrice 380 | | ); 381 | | 382 | | _signalPendingAction(actionKey, "setPriceFeed"); 383 | | 384 | | EventUtils.EventLogData memory eventData; 385 | | eventData.addressItems.initItems(2); 386 | | eventData.addressItems.setItem(0, "token", token); 387 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed); 388 | | eventData.uintItems.initItems(3); 389 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier); 390 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration); 391 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice); 392 | | eventEmitter.emitEventLog1( 393 | | "SignalSetPriceFeed", 394 | | actionKey, 395 | | eventData 396 | | ); 397 | | } 398 | | 399 | | // @dev sets a price feed 400 | | // @param token the token to set the price feed for 401 | | // @param priceFeed the address of the price feed 402 | | // @param priceFeedMultiplier the multiplier to apply to the price feed results 403 | | // @param stablePrice the stable price to set a range for the price feed results 404 | | function setPriceFeedAfterSignal( 405 | | address token, 406 | | address priceFeed, 407 | | uint256 priceFeedMultiplier, 408 | | uint256 priceFeedHeartbeatDuration, 409 | | uint256 stablePrice 410 | | ) external onlyTimelockAdmin nonReentrant { 411 | | bytes32 actionKey = _setPriceFeedActionKey( 412 | | token, 413 | | priceFeed, 414 | | priceFeedMultiplier, 415 | | priceFeedHeartbeatDuration, 416 | | stablePrice 417 | | ); 418 | | 419 | | _validateAndClearAction(actionKey, "setPriceFeed"); 420 | | 421 | | dataStore.setAddress(Keys.priceFeedKey(token), priceFeed); 422 | | dataStore.setUint(Keys.priceFeedMultiplierKey(token), priceFeedMultiplier); 423 | | dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration); 424 | | dataStore.setUint(Keys.stablePriceKey(token), stablePrice); 425 | | 426 | | EventUtils.EventLogData memory eventData; 427 | | eventData.addressItems.initItems(2); 428 | | eventData.addressItems.setItem(0, "token", token); 429 | | eventData.addressItems.setItem(1, "priceFeed", priceFeed); 430 | | eventData.uintItems.initItems(3); 431 | | eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier); 432 | | eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration); 433 | | eventData.uintItems.setItem(2, "stablePrice", stablePrice); 434 | | eventEmitter.emitEventLog1( 435 | | "SetPriceFeed", 436 | | actionKey, 437 | | eventData 438 | | ); 439 | | } 440 | | 441 | | // @dev signal setting of a data stream feed 442 | | // @param token the token to set the data stream feed for 443 | | // @param feedId the ID of the data stream feed 444 | | // @param dataStreamMultiplier the multiplier to apply to the data stream feed results 445 | | function signalSetDataStream( 446 | | address token, 447 | | bytes32 feedId, 448 | | uint256 dataStreamMultiplier 449 | | ) external onlyTimelockAdmin nonReentrant { 450 | | bytes32 actionKey = _setDataStreamActionKey( 451 | | token, 452 | | feedId, 453 | | dataStreamMultiplier 454 | | ); 455 | | 456 | | _signalPendingAction(actionKey, "setDataStream"); 457 | | 458 | | EventUtils.EventLogData memory eventData; 459 | | eventData.addressItems.initItems(1); 460 | | eventData.addressItems.setItem(0, "token", token); 461 | | eventData.bytes32Items.initItems(1); 462 | | eventData.bytes32Items.setItem(0, "feedId", feedId); 463 | | eventData.uintItems.initItems(1); 464 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier); 465 | | eventEmitter.emitEventLog1( 466 | | "SignalSetDataStream", 467 | | actionKey, 468 | | eventData 469 | | ); 470 | | } 471 | | 472 | | // @dev sets a data stream feed 473 | | // @param token the token to set the data stream feed for 474 | | // @param feedId the ID of the data stream feed 475 | | // @param dataStreamMultiplier the multiplier to apply to the data stream feed results 476 | | function setDataStreamAfterSignal( 477 | | address token, 478 | | bytes32 feedId, 479 | | uint256 dataStreamMultiplier 480 | | ) external onlyTimelockAdmin nonReentrant { 481 | | bytes32 actionKey = _setDataStreamActionKey( 482 | | token, 483 | | feedId, 484 | | dataStreamMultiplier 485 | | ); 486 | | 487 | | _validateAndClearAction(actionKey, "setDataStream"); 488 | | 489 | | dataStore.setBytes32(Keys.dataStreamIdKey(token), feedId); 490 | | dataStore.setUint(Keys.dataStreamMultiplierKey(token), dataStreamMultiplier); 491 | | 492 | | EventUtils.EventLogData memory eventData; 493 | | eventData.addressItems.initItems(1); 494 | | eventData.addressItems.setItem(0, "token", token); 495 | | eventData.bytes32Items.initItems(1); 496 | | eventData.bytes32Items.setItem(0, "feedId", feedId); 497 | | eventData.uintItems.initItems(1); 498 | | eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier); 499 | | eventEmitter.emitEventLog1( 500 | | "SetDataStream", 501 | | actionKey, 502 | | eventData 503 | | ); 504 | | } 505 | | 506 | | // @dev cancels a previously signalled pending action 507 | | // @param actionKey the key of the action to cancel 508 | | function cancelAction(bytes32 actionKey) external onlyTimelockAdmin nonReentrant { 509 | | _clearAction(actionKey, "cancelAction"); 510 | | } 511 | | 512 | | // @dev signal a pending action 513 | | // @param actionKey the key of the action 514 | | // @param actionLabel a label for the action 515 | | function _signalPendingAction(bytes32 actionKey, string memory actionLabel) internal { 516 | | if (pendingActions[actionKey] != 0) { 517 | | revert Errors.ActionAlreadySignalled(); 518 | | } 519 | | 520 | | pendingActions[actionKey] = Chain.currentTimestamp() + timelockDelay; 521 | | pendingActionsList.add(actionKey); 522 | | 523 | | EventUtils.EventLogData memory eventData; 524 | | 525 | | eventData.bytes32Items.initItems(1); 526 | | eventData.bytes32Items.setItem(0, "actionKey", actionKey); 527 | | 528 | | eventData.stringItems.initItems(1); 529 | | eventData.stringItems.setItem(0, "actionLabel", actionLabel); 530 | | 531 | | eventEmitter.emitEventLog1( 532 | | "SignalPendingAction", 533 | | actionKey, 534 | | eventData 535 | | ); 536 | | } 537 | | 538 | | function _setOracleProviderEnabledKey(address provider, bool value) internal pure returns (bytes32) { 539 | | return keccak256(abi.encodePacked("setOracleProviderEnabled", provider, value)); 540 | | } 541 | | 542 | | function _setAtomicOracleProviderKey(address provider, bool value) internal pure returns (bytes32) { 543 | | return keccak256(abi.encodePacked("setAtomicOracleProvider", provider, value)); 544 | | } 545 | | 546 | | function _addOracleSignerActionKey(address account) internal pure returns (bytes32) { 547 | | return keccak256(abi.encodePacked("addOracleSigner", account)); 548 | | } 549 | | 550 | | function _removeOracleSignerActionKey(address account) internal pure returns (bytes32) { 551 | | return keccak256(abi.encodePacked("removeOracleSigner", account)); 552 | | } 553 | | 554 | | function _setFeeReceiverActionKey(address account) internal pure returns (bytes32) { 555 | | return keccak256(abi.encodePacked("setFeeReceiver", account)); 556 | | } 557 | | 558 | | function _grantRoleActionKey(address account, bytes32 roleKey) internal pure returns (bytes32) { 559 | | return keccak256(abi.encodePacked("grantRole", account, roleKey)); 560 | | } 561 | | 562 | | function _revokeRoleActionKey(address account, bytes32 roleKey) internal pure returns (bytes32) { 563 | | return keccak256(abi.encodePacked("revokeRole", account, roleKey)); 564 | | } 565 | | 566 | | function _setPriceFeedActionKey( 567 | | address token, 568 | | address priceFeed, 569 | | uint256 priceFeedMultiplier, 570 | | uint256 priceFeedHeartbeatDuration, 571 | | uint256 stablePrice 572 | | ) internal pure returns (bytes32) { 573 | | return keccak256(abi.encodePacked( 574 | | "setPriceFeed", 575 | | token, 576 | | priceFeed, 577 | | priceFeedMultiplier, 578 | | priceFeedHeartbeatDuration, 579 | | stablePrice 580 | | )); 581 | | } 582 | | 583 | | function _setDataStreamActionKey( 584 | | address token, 585 | | bytes32 feedId, 586 | | uint256 dataStreamMultiplier 587 | | ) internal pure returns (bytes32) { 588 | | return keccak256(abi.encodePacked( 589 | | "setDataStream", 590 | | token, 591 | | feedId, 592 | | dataStreamMultiplier 593 | | )); 594 | | } 595 | | 596 | | // @dev validate that the action has been signalled and sufficient time has 597 | | // passed, clear the action after 598 | | function _validateAndClearAction(bytes32 actionKey, string memory actionLabel) internal { 599 | | _validateAction(actionKey); 600 | | _clearAction(actionKey, actionLabel); 601 | | } 602 | | 603 | | // @dev validate that the action has been signalled and sufficient time has passed 604 | | function _validateAction(bytes32 actionKey) internal view { 605 | | if (pendingActions[actionKey] == 0) { 606 | | revert Errors.ActionNotSignalled(); 607 | | } 608 | | 609 | | if (pendingActions[actionKey] > Chain.currentTimestamp()) { 610 | | revert Errors.SignalTimeNotYetPassed(pendingActions[actionKey]); 611 | | } 612 | | } 613 | | 614 | | // @dev clear a previously signalled action 615 | | function _clearAction(bytes32 actionKey, string memory actionLabel) internal { 616 | | if (pendingActions[actionKey] == 0) { 617 | | revert Errors.ActionNotSignalled(); 618 | | } 619 | | delete pendingActions[actionKey]; 620 | | pendingActionsList.remove(actionKey); 621 | | 622 | | EventUtils.EventLogData memory eventData; 623 | | 624 | | eventData.bytes32Items.initItems(1); 625 | | eventData.bytes32Items.setItem(0, "actionKey", actionKey); 626 | | 627 | | eventData.stringItems.initItems(1); 628 | | eventData.stringItems.setItem(0, "actionLabel", actionLabel); 629 | | 630 | | eventEmitter.emitEventLog1( 631 | | "ClearPendingAction", 632 | | actionKey, 633 | | eventData 634 | | ); 635 | | } 636 | | 637 | | function _validateTimelockDelay() internal view { 638 | | if (timelockDelay > MAX_TIMELOCK_DELAY) { 639 | | revert Errors.MaxTimelockDelayExceeded(timelockDelay); 640 | | } 641 | | } 642 | | } 643 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/data/DataStore.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../role/RoleModule.sol"; 6 | | import "../utils/Calc.sol"; 7 | | import "../utils/Printer.sol"; 8 | | 9 | | // @title DataStore 10 | | // @dev DataStore for all general state values 11 | * | contract DataStore is RoleModule { 12 | | using SafeCast for int256; 13 | | 14 | | using EnumerableSet for EnumerableSet.Bytes32Set; 15 | | using EnumerableSet for EnumerableSet.AddressSet; 16 | | using EnumerableSet for EnumerableSet.UintSet; 17 | | using EnumerableValues for EnumerableSet.Bytes32Set; 18 | | using EnumerableValues for EnumerableSet.AddressSet; 19 | | using EnumerableValues for EnumerableSet.UintSet; 20 | | 21 | | // store for uint values 22 | | mapping(bytes32 => uint256) public uintValues; 23 | | // store for int values 24 | | mapping(bytes32 => int256) public intValues; 25 | | // store for address values 26 | | mapping(bytes32 => address) public addressValues; 27 | | // store for bool values 28 | | mapping(bytes32 => bool) public boolValues; 29 | | // store for string values 30 | | mapping(bytes32 => string) public stringValues; 31 | | // store for bytes32 values 32 | | mapping(bytes32 => bytes32) public bytes32Values; 33 | | 34 | | // store for uint[] values 35 | | mapping(bytes32 => uint256[]) public uintArrayValues; 36 | | // store for int[] values 37 | | mapping(bytes32 => int256[]) public intArrayValues; 38 | | // store for address[] values 39 | | mapping(bytes32 => address[]) public addressArrayValues; 40 | | // store for bool[] values 41 | | mapping(bytes32 => bool[]) public boolArrayValues; 42 | | // store for string[] values 43 | | mapping(bytes32 => string[]) public stringArrayValues; 44 | | // store for bytes32[] values 45 | | mapping(bytes32 => bytes32[]) public bytes32ArrayValues; 46 | | 47 | | // store for bytes32 sets 48 | | mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets; 49 | | // store for address sets 50 | | mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets; 51 | | // store for uint256 sets 52 | | mapping(bytes32 => EnumerableSet.UintSet) internal uintSets; 53 | | 54 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {} 55 | | 56 | | // @dev get the uint value for the given key 57 | | // @param key the key of the value 58 | | // @return the uint value for the key 59 | * | function getUint(bytes32 key) external view returns (uint256) { 60 | * | return uintValues[key]; 61 | | } 62 | | 63 | | // @dev set the uint value for the given key 64 | | // @param key the key of the value 65 | | // @param value the value to set 66 | | // @return the uint value for the key 67 | * | function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) { 68 | * | uintValues[key] = value; 69 | * | return value; 70 | | } 71 | | 72 | | // @dev delete the uint value for the given key 73 | | // @param key the key of the value 74 | * | function removeUint(bytes32 key) external onlyController { 75 | * | delete uintValues[key]; 76 | | } 77 | | 78 | | // @dev add the input int value to the existing uint value 79 | | // @param key the key of the value 80 | | // @param value the input int value 81 | | // @return the new uint value 82 | * | function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) { 83 | * | uint256 currValue = uintValues[key]; 84 | * | if (value < 0 && (-value).toUint256() > currValue) { 85 | * | revert(errorMessage); 86 | | } 87 | * | uint256 nextUint = Calc.sumReturnUint256(currValue, value); 88 | * | uintValues[key] = nextUint; 89 | * | return nextUint; 90 | | } 91 | | 92 | | // @dev add the input uint value to the existing uint value 93 | | // @param key the key of the value 94 | | // @param value the input int value 95 | | // @return the new uint value 96 | * | function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) { 97 | * | uint256 currValue = uintValues[key]; 98 | * | uint256 nextUint = currValue + value; 99 | * | uintValues[key] = nextUint; 100 | * | return nextUint; 101 | | } 102 | | 103 | | // @dev add the input int value to the existing uint value, prevent the uint 104 | | // value from becoming negative 105 | | // @param key the key of the value 106 | | // @param value the input int value 107 | | // @return the new uint value 108 | * | function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) { 109 | * | uint256 uintValue = uintValues[key]; 110 | * | if (value < 0 && (-value).toUint256() > uintValue) { 111 | | uintValues[key] = 0; 112 | | return 0; 113 | | } 114 | | 115 | * | uint256 nextUint = Calc.sumReturnUint256(uintValue, value); 116 | * | uintValues[key] = nextUint; 117 | * | return nextUint; 118 | | } 119 | | 120 | | // @dev add the input uint value to the existing uint value 121 | | // @param key the key of the value 122 | | // @param value the input uint value 123 | | // @return the new uint value 124 | * | function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) { 125 | * | uint256 nextUint = uintValues[key] + value; 126 | * | uintValues[key] = nextUint; 127 | * | return nextUint; 128 | | } 129 | | 130 | | // @dev subtract the input uint value from the existing uint value 131 | | // @param key the key of the value 132 | | // @param value the input uint value 133 | | // @return the new uint value 134 | * | function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) { 135 | * | uint256 nextUint = uintValues[key] - value; 136 | * | uintValues[key] = nextUint; 137 | * | return nextUint; 138 | | } 139 | | 140 | | // @dev get the int value for the given key 141 | | // @param key the key of the value 142 | | // @return the int value for the key 143 | | function getInt(bytes32 key) external view returns (int256) { 144 | | return intValues[key]; 145 | | } 146 | | 147 | | // @dev set the int value for the given key 148 | | // @param key the key of the value 149 | | // @param value the value to set 150 | | // @return the int value for the key 151 | * | function setInt(bytes32 key, int256 value) external onlyController returns (int256) { 152 | * | intValues[key] = value; 153 | * | return value; 154 | | } 155 | | 156 | | function removeInt(bytes32 key) external onlyController { 157 | | delete intValues[key]; 158 | | } 159 | | 160 | | // @dev add the input int value to the existing int value 161 | | // @param key the key of the value 162 | | // @param value the input int value 163 | | // @return the new int value 164 | | function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) { 165 | | int256 nextInt = intValues[key] + value; 166 | | intValues[key] = nextInt; 167 | | return nextInt; 168 | | } 169 | | 170 | | // @dev add the input int value to the existing int value 171 | | // @param key the key of the value 172 | | // @param value the input int value 173 | | // @return the new int value 174 | | function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) { 175 | | int256 nextInt = intValues[key] + value; 176 | | intValues[key] = nextInt; 177 | | return nextInt; 178 | | } 179 | | 180 | | // @dev subtract the input int value from the existing int value 181 | | // @param key the key of the value 182 | | // @param value the input int value 183 | | // @return the new int value 184 | | function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) { 185 | | int256 nextInt = intValues[key] - value; 186 | | intValues[key] = nextInt; 187 | | return nextInt; 188 | | } 189 | | 190 | | // @dev get the address value for the given key 191 | | // @param key the key of the value 192 | | // @return the address value for the key 193 | * | function getAddress(bytes32 key) external view returns (address) { 194 | * | return addressValues[key]; 195 | | } 196 | | 197 | | // @dev set the address value for the given key 198 | | // @param key the key of the value 199 | | // @param value the value to set 200 | | // @return the address value for the key 201 | * | function setAddress(bytes32 key, address value) external onlyController returns (address) { 202 | * | addressValues[key] = value; 203 | * | return value; 204 | | } 205 | | 206 | | // @dev delete the address value for the given key 207 | | // @param key the key of the value 208 | * | function removeAddress(bytes32 key) external onlyController { 209 | * | delete addressValues[key]; 210 | | } 211 | | 212 | | // @dev get the bool value for the given key 213 | | // @param key the key of the value 214 | | // @return the bool value for the key 215 | * | function getBool(bytes32 key) external view returns (bool) { 216 | * | return boolValues[key]; 217 | | } 218 | | 219 | | // @dev set the bool value for the given key 220 | | // @param key the key of the value 221 | | // @param value the value to set 222 | | // @return the bool value for the key 223 | * | function setBool(bytes32 key, bool value) external onlyController returns (bool) { 224 | * | boolValues[key] = value; 225 | * | return value; 226 | | } 227 | | 228 | | // @dev delete the bool value for the given key 229 | | // @param key the key of the value 230 | * | function removeBool(bytes32 key) external onlyController { 231 | * | delete boolValues[key]; 232 | | } 233 | | 234 | | // @dev get the string value for the given key 235 | | // @param key the key of the value 236 | | // @return the string value for the key 237 | | function getString(bytes32 key) external view returns (string memory) { 238 | | return stringValues[key]; 239 | | } 240 | | 241 | | // @dev set the string value for the given key 242 | | // @param key the key of the value 243 | | // @param value the value to set 244 | | // @return the string value for the key 245 | | function setString(bytes32 key, string memory value) external onlyController returns (string memory) { 246 | | stringValues[key] = value; 247 | | return value; 248 | | } 249 | | 250 | | // @dev delete the string value for the given key 251 | | // @param key the key of the value 252 | | function removeString(bytes32 key) external onlyController { 253 | | delete stringValues[key]; 254 | | } 255 | | 256 | | // @dev get the bytes32 value for the given key 257 | | // @param key the key of the value 258 | | // @return the bytes32 value for the key 259 | * | function getBytes32(bytes32 key) external view returns (bytes32) { 260 | * | return bytes32Values[key]; 261 | | } 262 | | 263 | | // @dev set the bytes32 value for the given key 264 | | // @param key the key of the value 265 | | // @param value the value to set 266 | | // @return the bytes32 value for the key 267 | | function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) { 268 | | bytes32Values[key] = value; 269 | | return value; 270 | | } 271 | | 272 | | // @dev delete the bytes32 value for the given key 273 | | // @param key the key of the value 274 | | function removeBytes32(bytes32 key) external onlyController { 275 | | delete bytes32Values[key]; 276 | | } 277 | | 278 | | // @dev get the uint array for the given key 279 | | // @param key the key of the uint array 280 | | // @return the uint array for the key 281 | | function getUintArray(bytes32 key) external view returns (uint256[] memory) { 282 | | return uintArrayValues[key]; 283 | | } 284 | | 285 | | // @dev set the uint array for the given key 286 | | // @param key the key of the uint array 287 | | // @param value the value of the uint array 288 | | function setUintArray(bytes32 key, uint256[] memory value) external onlyController { 289 | | uintArrayValues[key] = value; 290 | | } 291 | | 292 | | // @dev delete the uint array for the given key 293 | | // @param key the key of the uint array 294 | | // @param value the value of the uint array 295 | | function removeUintArray(bytes32 key) external onlyController { 296 | | delete uintArrayValues[key]; 297 | | } 298 | | 299 | | // @dev get the int array for the given key 300 | | // @param key the key of the int array 301 | | // @return the int array for the key 302 | | function getIntArray(bytes32 key) external view returns (int256[] memory) { 303 | | return intArrayValues[key]; 304 | | } 305 | | 306 | | // @dev set the int array for the given key 307 | | // @param key the key of the int array 308 | | // @param value the value of the int array 309 | | function setIntArray(bytes32 key, int256[] memory value) external onlyController { 310 | | intArrayValues[key] = value; 311 | | } 312 | | 313 | | // @dev delete the int array for the given key 314 | | // @param key the key of the int array 315 | | // @param value the value of the int array 316 | | function removeIntArray(bytes32 key) external onlyController { 317 | | delete intArrayValues[key]; 318 | | } 319 | | 320 | | // @dev get the address array for the given key 321 | | // @param key the key of the address array 322 | | // @return the address array for the key 323 | * | function getAddressArray(bytes32 key) external view returns (address[] memory) { 324 | * | return addressArrayValues[key]; 325 | | } 326 | | 327 | | // @dev set the address array for the given key 328 | | // @param key the key of the address array 329 | | // @param value the value of the address array 330 | * | function setAddressArray(bytes32 key, address[] memory value) external onlyController { 331 | * | addressArrayValues[key] = value; 332 | | } 333 | | 334 | | // @dev delete the address array for the given key 335 | | // @param key the key of the address array 336 | | // @param value the value of the address array 337 | * | function removeAddressArray(bytes32 key) external onlyController { 338 | * | delete addressArrayValues[key]; 339 | | } 340 | | 341 | | // @dev get the bool array for the given key 342 | | // @param key the key of the bool array 343 | | // @return the bool array for the key 344 | | function getBoolArray(bytes32 key) external view returns (bool[] memory) { 345 | | return boolArrayValues[key]; 346 | | } 347 | | 348 | | // @dev set the bool array for the given key 349 | | // @param key the key of the bool array 350 | | // @param value the value of the bool array 351 | | function setBoolArray(bytes32 key, bool[] memory value) external onlyController { 352 | | boolArrayValues[key] = value; 353 | | } 354 | | 355 | | // @dev delete the bool array for the given key 356 | | // @param key the key of the bool array 357 | | // @param value the value of the bool array 358 | | function removeBoolArray(bytes32 key) external onlyController { 359 | | delete boolArrayValues[key]; 360 | | } 361 | | 362 | | // @dev get the string array for the given key 363 | | // @param key the key of the string array 364 | | // @return the string array for the key 365 | | function getStringArray(bytes32 key) external view returns (string[] memory) { 366 | | return stringArrayValues[key]; 367 | | } 368 | | 369 | | // @dev set the string array for the given key 370 | | // @param key the key of the string array 371 | | // @param value the value of the string array 372 | | function setStringArray(bytes32 key, string[] memory value) external onlyController { 373 | | stringArrayValues[key] = value; 374 | | } 375 | | 376 | | // @dev delete the string array for the given key 377 | | // @param key the key of the string array 378 | | // @param value the value of the string array 379 | | function removeStringArray(bytes32 key) external onlyController { 380 | | delete stringArrayValues[key]; 381 | | } 382 | | 383 | | // @dev get the bytes32 array for the given key 384 | | // @param key the key of the bytes32 array 385 | | // @return the bytes32 array for the key 386 | | function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) { 387 | | return bytes32ArrayValues[key]; 388 | | } 389 | | 390 | | // @dev set the bytes32 array for the given key 391 | | // @param key the key of the bytes32 array 392 | | // @param value the value of the bytes32 array 393 | | function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController { 394 | | bytes32ArrayValues[key] = value; 395 | | } 396 | | 397 | | // @dev delete the bytes32 array for the given key 398 | | // @param key the key of the bytes32 array 399 | | // @param value the value of the bytes32 array 400 | | function removeBytes32Array(bytes32 key) external onlyController { 401 | | delete bytes32ArrayValues[key]; 402 | | } 403 | | 404 | | // @dev check whether the given value exists in the set 405 | | // @param setKey the key of the set 406 | | // @param value the value to check 407 | * | function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) { 408 | * | return bytes32Sets[setKey].contains(value); 409 | | } 410 | | 411 | | // @dev get the length of the set 412 | | // @param setKey the key of the set 413 | * | function getBytes32Count(bytes32 setKey) external view returns (uint256) { 414 | * | return bytes32Sets[setKey].length(); 415 | | } 416 | | 417 | | // @dev get the values of the set in the given range 418 | | // @param setKey the key of the set 419 | | // @param the start of the range, values at the start index will be returned 420 | | // in the result 421 | | // @param the end of the range, values at the end index will not be returned 422 | | // in the result 423 | * | function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) { 424 | * | return bytes32Sets[setKey].valuesAt(start, end); 425 | | } 426 | | 427 | | // @dev add the given value to the set 428 | | // @param setKey the key of the set 429 | | // @param value the value to add 430 | * | function addBytes32(bytes32 setKey, bytes32 value) external onlyController { 431 | * | bytes32Sets[setKey].add(value); 432 | | } 433 | | 434 | | // @dev remove the given value from the set 435 | | // @param setKey the key of the set 436 | | // @param value the value to remove 437 | * | function removeBytes32(bytes32 setKey, bytes32 value) external onlyController { 438 | * | bytes32Sets[setKey].remove(value); 439 | | } 440 | | 441 | | // @dev check whether the given value exists in the set 442 | | // @param setKey the key of the set 443 | | // @param value the value to check 444 | * | function containsAddress(bytes32 setKey, address value) external view returns (bool) { 445 | * | return addressSets[setKey].contains(value); 446 | | } 447 | | 448 | | // @dev get the length of the set 449 | | // @param setKey the key of the set 450 | | function getAddressCount(bytes32 setKey) external view returns (uint256) { 451 | | return addressSets[setKey].length(); 452 | | } 453 | | 454 | | // @dev get the values of the set in the given range 455 | | // @param setKey the key of the set 456 | | // @param the start of the range, values at the start index will be returned 457 | | // in the result 458 | | // @param the end of the range, values at the end index will not be returned 459 | | // in the result 460 | | function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) { 461 | | return addressSets[setKey].valuesAt(start, end); 462 | | } 463 | | 464 | | // @dev add the given value to the set 465 | | // @param setKey the key of the set 466 | | // @param value the value to add 467 | | function addAddress(bytes32 setKey, address value) external onlyController { 468 | | addressSets[setKey].add(value); 469 | | } 470 | | 471 | | // @dev remove the given value from the set 472 | | // @param setKey the key of the set 473 | | // @param value the value to remove 474 | | function removeAddress(bytes32 setKey, address value) external onlyController { 475 | | addressSets[setKey].remove(value); 476 | | } 477 | | 478 | | // @dev check whether the given value exists in the set 479 | | // @param setKey the key of the set 480 | | // @param value the value to check 481 | | function containsUint(bytes32 setKey, uint256 value) external view returns (bool) { 482 | | return uintSets[setKey].contains(value); 483 | | } 484 | | 485 | | // @dev get the length of the set 486 | | // @param setKey the key of the set 487 | | function getUintCount(bytes32 setKey) external view returns (uint256) { 488 | | return uintSets[setKey].length(); 489 | | } 490 | | 491 | | // @dev get the values of the set in the given range 492 | | // @param setKey the key of the set 493 | | // @param the start of the range, values at the start index will be returned 494 | | // in the result 495 | | // @param the end of the range, values at the end index will not be returned 496 | | // in the result 497 | | function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) { 498 | | return uintSets[setKey].valuesAt(start, end); 499 | | } 500 | | 501 | | // @dev add the given value to the set 502 | | // @param setKey the key of the set 503 | | // @param value the value to add 504 | | function addUint(bytes32 setKey, uint256 value) external onlyController { 505 | | uintSets[setKey].add(value); 506 | | } 507 | | 508 | | // @dev remove the given value from the set 509 | | // @param setKey the key of the set 510 | | // @param value the value to remove 511 | | function removeUint(bytes32 setKey, uint256 value) external onlyController { 512 | | uintSets[setKey].remove(value); 513 | | } 514 | | } 515 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/data/Keys.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title Keys 6 | | // @dev Keys for values in the DataStore 7 | * | library Keys { 8 | | // @dev key for the address of the wrapped native token 9 | * | bytes32 internal constant WNT = keccak256(abi.encode("WNT")); 10 | | // @dev key for the nonce value used in NonceUtils 11 | * | bytes32 internal constant NONCE = keccak256(abi.encode("NONCE")); 12 | | 13 | | // @dev for sending received fees 14 | | bytes32 internal constant FEE_RECEIVER = keccak256(abi.encode("FEE_RECEIVER")); 15 | | 16 | | // @dev for holding tokens that could not be sent out 17 | | bytes32 internal constant HOLDING_ADDRESS = keccak256(abi.encode("HOLDING_ADDRESS")); 18 | | 19 | | // @dev key for the minimum gas for execution error 20 | | bytes32 internal constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS")); 21 | | 22 | | // @dev key for the minimum gas that should be forwarded for execution error handling 23 | * | bytes32 internal constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD")); 24 | | 25 | | // @dev key for the min additional gas for execution 26 | * | bytes32 internal constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode("MIN_ADDITIONAL_GAS_FOR_EXECUTION")); 27 | | 28 | | // @dev for a global reentrancy guard 29 | * | bytes32 internal constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode("REENTRANCY_GUARD_STATUS")); 30 | | 31 | | // @dev key for deposit fees 32 | * | bytes32 internal constant DEPOSIT_FEE_TYPE = keccak256(abi.encode("DEPOSIT_FEE_TYPE")); 33 | | // @dev key for withdrawal fees 34 | * | bytes32 internal constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("WITHDRAWAL_FEE_TYPE")); 35 | | // @dev key for swap fees 36 | * | bytes32 internal constant SWAP_FEE_TYPE = keccak256(abi.encode("SWAP_FEE_TYPE")); 37 | | // @dev key for position fees 38 | * | bytes32 internal constant POSITION_FEE_TYPE = keccak256(abi.encode("POSITION_FEE_TYPE")); 39 | | // @dev key for ui deposit fees 40 | * | bytes32 internal constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode("UI_DEPOSIT_FEE_TYPE")); 41 | | // @dev key for ui withdrawal fees 42 | * | bytes32 internal constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("UI_WITHDRAWAL_FEE_TYPE")); 43 | | // @dev key for ui swap fees 44 | * | bytes32 internal constant UI_SWAP_FEE_TYPE = keccak256(abi.encode("UI_SWAP_FEE_TYPE")); 45 | | // @dev key for ui position fees 46 | * | bytes32 internal constant UI_POSITION_FEE_TYPE = keccak256(abi.encode("UI_POSITION_FEE_TYPE")); 47 | | 48 | | // @dev key for ui fee factor 49 | * | bytes32 internal constant UI_FEE_FACTOR = keccak256(abi.encode("UI_FEE_FACTOR")); 50 | | // @dev key for max ui fee receiver factor 51 | * | bytes32 internal constant MAX_UI_FEE_FACTOR = keccak256(abi.encode("MAX_UI_FEE_FACTOR")); 52 | | 53 | | // @dev key for the claimable fee amount 54 | * | bytes32 internal constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_FEE_AMOUNT")); 55 | | // @dev key for the claimable ui fee amount 56 | * | bytes32 internal constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_UI_FEE_AMOUNT")); 57 | | // @dev key for the max number of auto cancel orders 58 | * | bytes32 internal constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_AUTO_CANCEL_ORDERS")); 59 | | // @dev key for the max total callback gas limit for auto cancel orders 60 | * | bytes32 internal constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS")); 61 | | 62 | | // @dev key for the market list 63 | * | bytes32 internal constant MARKET_LIST = keccak256(abi.encode("MARKET_LIST")); 64 | | 65 | | // @dev key for the fee batch list 66 | | bytes32 internal constant FEE_BATCH_LIST = keccak256(abi.encode("FEE_BATCH_LIST")); 67 | | 68 | | // @dev key for the deposit list 69 | * | bytes32 internal constant DEPOSIT_LIST = keccak256(abi.encode("DEPOSIT_LIST")); 70 | | // @dev key for the account deposit list 71 | * | bytes32 internal constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_DEPOSIT_LIST")); 72 | | 73 | | // @dev key for the withdrawal list 74 | * | bytes32 internal constant WITHDRAWAL_LIST = keccak256(abi.encode("WITHDRAWAL_LIST")); 75 | | // @dev key for the account withdrawal list 76 | * | bytes32 internal constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode("ACCOUNT_WITHDRAWAL_LIST")); 77 | | 78 | | // @dev key for the shift list 79 | | bytes32 internal constant SHIFT_LIST = keccak256(abi.encode("SHIFT_LIST")); 80 | | // @dev key for the account shift list 81 | | bytes32 internal constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode("ACCOUNT_SHIFT_LIST")); 82 | | 83 | | // @dev key for the glv list 84 | | bytes32 internal constant GLV_LIST = keccak256(abi.encode("GLV_LIST")); 85 | | 86 | | // @dev key for the glv deposit list 87 | | bytes32 internal constant GLV_DEPOSIT_LIST = keccak256(abi.encode("GLV_DEPOSIT_LIST")); 88 | | // @dev key for the account glv deposit list 89 | | bytes32 internal constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_GLV_DEPOSIT_LIST")); 90 | | // @dev key for the account glv supported market list 91 | | bytes32 internal constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode("GLV_SUPPORTED_MARKET_LIST")); 92 | | 93 | | // @dev key for the position list 94 | * | bytes32 internal constant POSITION_LIST = keccak256(abi.encode("POSITION_LIST")); 95 | | // @dev key for the account position list 96 | * | bytes32 internal constant ACCOUNT_POSITION_LIST = keccak256(abi.encode("ACCOUNT_POSITION_LIST")); 97 | | 98 | | // @dev key for the order list 99 | * | bytes32 internal constant ORDER_LIST = keccak256(abi.encode("ORDER_LIST")); 100 | | // @dev key for the account order list 101 | * | bytes32 internal constant ACCOUNT_ORDER_LIST = keccak256(abi.encode("ACCOUNT_ORDER_LIST")); 102 | | 103 | | // @dev key for the subaccount list 104 | | bytes32 internal constant SUBACCOUNT_LIST = keccak256(abi.encode("SUBACCOUNT_LIST")); 105 | | 106 | | // @dev key for the auto cancel order list 107 | * | bytes32 internal constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode("AUTO_CANCEL_ORDER_LIST")); 108 | | 109 | | // @dev key for is market disabled 110 | * | bytes32 internal constant IS_MARKET_DISABLED = keccak256(abi.encode("IS_MARKET_DISABLED")); 111 | | 112 | | // @dev key for the max swap path length allowed 113 | * | bytes32 internal constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode("MAX_SWAP_PATH_LENGTH")); 114 | | // @dev key used to store markets observed in a swap path, to ensure that a swap path contains unique markets 115 | * | bytes32 internal constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode("SWAP_PATH_MARKET_FLAG")); 116 | | // @dev key used to store the min market tokens for the first deposit for a market 117 | | bytes32 internal constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode("MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT")); 118 | | 119 | | // @dev key for whether the create glv deposit feature is disabled 120 | | bytes32 internal constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_GLV_DEPOSIT_FEATURE_DISABLED")); 121 | | // @dev key for whether the cancel glv deposit feature is disabled 122 | | bytes32 internal constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_GLV_DEPOSIT_FEATURE_DISABLED")); 123 | | // @dev key for whether the execute glv deposit feature is disabled 124 | | bytes32 internal constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED")); 125 | | // @dev key for whether the glv shift feature is disabled 126 | | bytes32 internal constant GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("GLV_SHIFT_FEATURE_DISABLED")); 127 | | 128 | | // @dev key for whether the create deposit feature is disabled 129 | * | bytes32 internal constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_DEPOSIT_FEATURE_DISABLED")); 130 | | // @dev key for whether the cancel deposit feature is disabled 131 | * | bytes32 internal constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_DEPOSIT_FEATURE_DISABLED")); 132 | | // @dev key for whether the execute deposit feature is disabled 133 | * | bytes32 internal constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_DEPOSIT_FEATURE_DISABLED")); 134 | | 135 | | // @dev key for whether the create withdrawal feature is disabled 136 | * | bytes32 internal constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CREATE_WITHDRAWAL_FEATURE_DISABLED")); 137 | | // @dev key for whether the cancel withdrawal feature is disabled 138 | * | bytes32 internal constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_WITHDRAWAL_FEATURE_DISABLED")); 139 | | // @dev key for whether the execute withdrawal feature is disabled 140 | * | bytes32 internal constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_WITHDRAWAL_FEATURE_DISABLED")); 141 | | // @dev key for whether the execute atomic withdrawal feature is disabled 142 | * | bytes32 internal constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED")); 143 | | 144 | | // @dev key for whether the create shift feature is disabled 145 | | bytes32 internal constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_SHIFT_FEATURE_DISABLED")); 146 | | // @dev key for whether the cancel shift feature is disabled 147 | | bytes32 internal constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_SHIFT_FEATURE_DISABLED")); 148 | | // @dev key for whether the execute shift feature is disabled 149 | | bytes32 internal constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_SHIFT_FEATURE_DISABLED")); 150 | | 151 | | // @dev key for whether the create order feature is disabled 152 | * | bytes32 internal constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CREATE_ORDER_FEATURE_DISABLED")); 153 | | // @dev key for whether the execute order feature is disabled 154 | * | bytes32 internal constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ORDER_FEATURE_DISABLED")); 155 | | // @dev key for whether the execute adl feature is disabled 156 | | // for liquidations, it can be disabled by using the EXECUTE_ORDER_FEATURE_DISABLED key with the Liquidation 157 | | // order type, ADL orders have a MarketDecrease order type, so a separate key is needed to disable it 158 | * | bytes32 internal constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ADL_FEATURE_DISABLED")); 159 | | // @dev key for whether the update order feature is disabled 160 | | bytes32 internal constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("UPDATE_ORDER_FEATURE_DISABLED")); 161 | | // @dev key for whether the cancel order feature is disabled 162 | * | bytes32 internal constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_ORDER_FEATURE_DISABLED")); 163 | | 164 | | // @dev key for whether the claim funding fees feature is disabled 165 | * | bytes32 internal constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_FUNDING_FEES_FEATURE_DISABLED")); 166 | | // @dev key for whether the claim collateral feature is disabled 167 | | bytes32 internal constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_COLLATERAL_FEATURE_DISABLED")); 168 | | // @dev key for whether the claim affiliate rewards feature is disabled 169 | | bytes32 internal constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED")); 170 | | // @dev key for whether the claim ui fees feature is disabled 171 | | bytes32 internal constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_UI_FEES_FEATURE_DISABLED")); 172 | | // @dev key for whether the subaccount feature is disabled 173 | | bytes32 internal constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode("SUBACCOUNT_FEATURE_DISABLED")); 174 | | 175 | | // @dev key for the minimum required oracle signers for an oracle observation 176 | | bytes32 internal constant MIN_ORACLE_SIGNERS = keccak256(abi.encode("MIN_ORACLE_SIGNERS")); 177 | | // @dev key for the minimum block confirmations before blockhash can be excluded for oracle signature validation 178 | | bytes32 internal constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode("MIN_ORACLE_BLOCK_CONFIRMATIONS")); 179 | | // @dev key for the maximum usable oracle price age in seconds 180 | * | bytes32 internal constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode("MAX_ORACLE_PRICE_AGE")); 181 | | // @dev key for the maximum oracle timestamp range 182 | * | bytes32 internal constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode("MAX_ORACLE_TIMESTAMP_RANGE")); 183 | | // @dev key for the maximum oracle price deviation factor from the ref price 184 | * | bytes32 internal constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode("MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR")); 185 | | // @dev key for whether an oracle provider is enabled 186 | * | bytes32 internal constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode("IS_ORACLE_PROVIDER_ENABLED")); 187 | | // @dev key for whether an oracle provider can be used for atomic actions 188 | * | bytes32 internal constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode("IS_ATOMIC_ORACLE_PROVIDER")); 189 | | // @dev key for oracle timestamp adjustment 190 | | bytes32 internal constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode("ORACLE_TIMESTAMP_ADJUSTMENT")); 191 | | // @dev key for oracle provider for token 192 | * | bytes32 internal constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode("ORACLE_PROVIDER_FOR_TOKEN")); 193 | | // @dev key for the chainlink payment token 194 | | bytes32 internal constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode("CHAINLINK_PAYMENT_TOKEN")); 195 | | // @dev key for the sequencer grace duration 196 | | bytes32 internal constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode("SEQUENCER_GRACE_DURATION")); 197 | | 198 | | // @dev key for the percentage amount of position fees to be received 199 | * | bytes32 internal constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode("POSITION_FEE_RECEIVER_FACTOR")); 200 | | // @dev key for the percentage amount of swap fees to be received 201 | * | bytes32 internal constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode("SWAP_FEE_RECEIVER_FACTOR")); 202 | | // @dev key for the percentage amount of borrowing fees to be received 203 | * | bytes32 internal constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode("BORROWING_FEE_RECEIVER_FACTOR")); 204 | | 205 | | // @dev key for the base gas limit used when estimating execution fee 206 | * | bytes32 internal constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1")); 207 | | // @dev key for the gas limit used for each oracle price when estimating execution fee 208 | * | bytes32 internal constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE")); 209 | | // @dev key for the multiplier used when estimating execution fee 210 | * | bytes32 internal constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR")); 211 | | 212 | | // @dev key for the base gas limit used when calculating execution fee 213 | * | bytes32 internal constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1")); 214 | | // @dev key for the gas limit used for each oracle price 215 | * | bytes32 internal constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("EXECUTION_GAS_FEE_PER_ORACLE_PRICE")); 216 | | // @dev key for the multiplier used when calculating execution fee 217 | * | bytes32 internal constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("EXECUTION_GAS_FEE_MULTIPLIER_FACTOR")); 218 | | 219 | | // @dev key for the estimated gas limit for deposits 220 | * | bytes32 internal constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode("DEPOSIT_GAS_LIMIT")); 221 | | // @dev key for the estimated gas limit for withdrawals 222 | * | bytes32 internal constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode("WITHDRAWAL_GAS_LIMIT")); 223 | | // @dev key for the estimated gas limit for each glv market 224 | | bytes32 internal constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode("GLV_DEPOSIT_GAS_LIMIT")); 225 | | // @dev key for the estimated gas limit for shifts 226 | | bytes32 internal constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode("GLV_PER_MARKET_GAS_LIMIT")); 227 | | // @dev key for the estimated gas limit for shifts 228 | | bytes32 internal constant SHIFT_GAS_LIMIT = keccak256(abi.encode("SHIFT_GAS_LIMIT")); 229 | | // @dev key for the estimated gas limit for single swaps 230 | * | bytes32 internal constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode("SINGLE_SWAP_GAS_LIMIT")); 231 | | // @dev key for the estimated gas limit for increase orders 232 | * | bytes32 internal constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("INCREASE_ORDER_GAS_LIMIT")); 233 | | // @dev key for the estimated gas limit for decrease orders 234 | * | bytes32 internal constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("DECREASE_ORDER_GAS_LIMIT")); 235 | | // @dev key for the estimated gas limit for swap orders 236 | * | bytes32 internal constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode("SWAP_ORDER_GAS_LIMIT")); 237 | | // @dev key for the amount of gas to forward for token transfers 238 | * | bytes32 internal constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("TOKEN_TRANSFER_GAS_LIMIT")); 239 | | // @dev key for the amount of gas to forward for native token transfers 240 | | bytes32 internal constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("NATIVE_TOKEN_TRANSFER_GAS_LIMIT")); 241 | | // @dev key for the request expiration time, after which the request will be considered expired 242 | * | bytes32 internal constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode("REQUEST_EXPIRATION_TIME")); 243 | | 244 | * | bytes32 internal constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode("MAX_CALLBACK_GAS_LIMIT")); 245 | * | bytes32 internal constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode("REFUND_EXECUTION_FEE_GAS_LIMIT")); 246 | * | bytes32 internal constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode("SAVED_CALLBACK_CONTRACT")); 247 | | 248 | | // @dev key for the min collateral factor 249 | * | bytes32 internal constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode("MIN_COLLATERAL_FACTOR")); 250 | | // @dev key for the min collateral factor for open interest multiplier 251 | * | bytes32 internal constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode("MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER")); 252 | | // @dev key for the min allowed collateral in USD 253 | * | bytes32 internal constant MIN_COLLATERAL_USD = keccak256(abi.encode("MIN_COLLATERAL_USD")); 254 | | // @dev key for the min allowed position size in USD 255 | * | bytes32 internal constant MIN_POSITION_SIZE_USD = keccak256(abi.encode("MIN_POSITION_SIZE_USD")); 256 | | 257 | | // @dev key for the virtual id of tokens 258 | * | bytes32 internal constant VIRTUAL_TOKEN_ID = keccak256(abi.encode("VIRTUAL_TOKEN_ID")); 259 | | // @dev key for the virtual id of markets 260 | * | bytes32 internal constant VIRTUAL_MARKET_ID = keccak256(abi.encode("VIRTUAL_MARKET_ID")); 261 | | // @dev key for the virtual inventory for swaps 262 | | bytes32 internal constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_SWAPS")); 263 | | // @dev key for the virtual inventory for positions 264 | | bytes32 internal constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_POSITIONS")); 265 | | 266 | | // @dev key for the position impact factor 267 | * | bytes32 internal constant POSITION_IMPACT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_FACTOR")); 268 | | // @dev key for the position impact exponent factor 269 | * | bytes32 internal constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_EXPONENT_FACTOR")); 270 | | // @dev key for the max decrease position impact factor 271 | * | bytes32 internal constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR")); 272 | | // @dev key for the max position impact factor for liquidations 273 | | bytes32 internal constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS")); 274 | | // @dev key for the position fee factor 275 | * | bytes32 internal constant POSITION_FEE_FACTOR = keccak256(abi.encode("POSITION_FEE_FACTOR")); 276 | | // @dev key for the swap impact factor 277 | * | bytes32 internal constant SWAP_IMPACT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_FACTOR")); 278 | | // @dev key for the swap impact exponent factor 279 | * | bytes32 internal constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_EXPONENT_FACTOR")); 280 | | // @dev key for the swap fee factor 281 | * | bytes32 internal constant SWAP_FEE_FACTOR = keccak256(abi.encode("SWAP_FEE_FACTOR")); 282 | | // @dev key for the atomic swap fee factor 283 | * | bytes32 internal constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode("ATOMIC_SWAP_FEE_FACTOR")); 284 | | // @dev key for the oracle type 285 | | bytes32 internal constant ORACLE_TYPE = keccak256(abi.encode("ORACLE_TYPE")); 286 | | // @dev key for open interest 287 | * | bytes32 internal constant OPEN_INTEREST = keccak256(abi.encode("OPEN_INTEREST")); 288 | | // @dev key for open interest in tokens 289 | * | bytes32 internal constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode("OPEN_INTEREST_IN_TOKENS")); 290 | | // @dev key for collateral sum for a market 291 | * | bytes32 internal constant COLLATERAL_SUM = keccak256(abi.encode("COLLATERAL_SUM")); 292 | | // @dev key for pool amount 293 | * | bytes32 internal constant POOL_AMOUNT = keccak256(abi.encode("POOL_AMOUNT")); 294 | | // @dev key for max pool amount 295 | * | bytes32 internal constant MAX_POOL_AMOUNT = keccak256(abi.encode("MAX_POOL_AMOUNT")); 296 | | // @dev key for max pool usd for deposit 297 | * | bytes32 internal constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode("MAX_POOL_USD_FOR_DEPOSIT")); 298 | | // @dev key for max open interest 299 | * | bytes32 internal constant MAX_OPEN_INTEREST = keccak256(abi.encode("MAX_OPEN_INTEREST")); 300 | | // @dev key for position impact pool amount 301 | * | bytes32 internal constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("POSITION_IMPACT_POOL_AMOUNT")); 302 | | // @dev key for min position impact pool amount 303 | | bytes32 internal constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("MIN_POSITION_IMPACT_POOL_AMOUNT")); 304 | | // @dev key for position impact pool distribution rate 305 | * | bytes32 internal constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTION_RATE")); 306 | | // @dev key for position impact pool distributed at 307 | * | bytes32 internal constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTED_AT")); 308 | | // @dev key for swap impact pool amount 309 | * | bytes32 internal constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode("SWAP_IMPACT_POOL_AMOUNT")); 310 | | // @dev key for price feed 311 | | bytes32 internal constant PRICE_FEED = keccak256(abi.encode("PRICE_FEED")); 312 | | // @dev key for price feed multiplier 313 | | bytes32 internal constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode("PRICE_FEED_MULTIPLIER")); 314 | | // @dev key for price feed heartbeat 315 | | bytes32 internal constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode("PRICE_FEED_HEARTBEAT_DURATION")); 316 | | // @dev key for data stream feed id 317 | | bytes32 internal constant DATA_STREAM_ID = keccak256(abi.encode("DATA_STREAM_ID")); 318 | | // @dev key for data stream feed multipler 319 | | bytes32 internal constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode("DATA_STREAM_MULTIPLIER")); 320 | | // @dev key for stable price 321 | | bytes32 internal constant STABLE_PRICE = keccak256(abi.encode("STABLE_PRICE")); 322 | | // @dev key for reserve factor 323 | * | bytes32 internal constant RESERVE_FACTOR = keccak256(abi.encode("RESERVE_FACTOR")); 324 | | // @dev key for open interest reserve factor 325 | * | bytes32 internal constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode("OPEN_INTEREST_RESERVE_FACTOR")); 326 | | // @dev key for max pnl factor 327 | * | bytes32 internal constant MAX_PNL_FACTOR = keccak256(abi.encode("MAX_PNL_FACTOR")); 328 | | // @dev key for max pnl factor 329 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS")); 330 | | // @dev key for max pnl factor for adl 331 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_ADL")); 332 | | // @dev key for min pnl factor for adl 333 | * | bytes32 internal constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode("MIN_PNL_FACTOR_AFTER_ADL")); 334 | | // @dev key for max pnl factor 335 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_DEPOSITS")); 336 | | // @dev key for max pnl factor for withdrawals 337 | * | bytes32 internal constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_WITHDRAWALS")); 338 | | // @dev key for latest ADL at 339 | * | bytes32 internal constant LATEST_ADL_AT = keccak256(abi.encode("LATEST_ADL_AT")); 340 | | // @dev key for whether ADL is enabled 341 | * | bytes32 internal constant IS_ADL_ENABLED = keccak256(abi.encode("IS_ADL_ENABLED")); 342 | | // @dev key for funding factor 343 | * | bytes32 internal constant FUNDING_FACTOR = keccak256(abi.encode("FUNDING_FACTOR")); 344 | | // @dev key for funding exponent factor 345 | * | bytes32 internal constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode("FUNDING_EXPONENT_FACTOR")); 346 | | // @dev key for saved funding factor 347 | * | bytes32 internal constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("SAVED_FUNDING_FACTOR_PER_SECOND")); 348 | | // @dev key for funding increase factor 349 | * | bytes32 internal constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_INCREASE_FACTOR_PER_SECOND")); 350 | | // @dev key for funding decrease factor 351 | | bytes32 internal constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_DECREASE_FACTOR_PER_SECOND")); 352 | | // @dev key for min funding factor 353 | | bytes32 internal constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MIN_FUNDING_FACTOR_PER_SECOND")); 354 | | // @dev key for max funding factor 355 | * | bytes32 internal constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MAX_FUNDING_FACTOR_PER_SECOND")); 356 | | // @dev key for max funding factor limit 357 | | bytes32 internal constant MAX_FUNDING_FACTOR_PER_SECOND_LIMIT = keccak256(abi.encode("MAX_FUNDING_FACTOR_PER_SECOND_LIMIT")); 358 | | // @dev key for threshold for stable funding 359 | | bytes32 internal constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_STABLE_FUNDING")); 360 | | // @dev key for threshold for decrease funding 361 | | bytes32 internal constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_DECREASE_FUNDING")); 362 | | // @dev key for funding fee amount per size 363 | * | bytes32 internal constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE")); 364 | | // @dev key for claimable funding amount per size 365 | * | bytes32 internal constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT_PER_SIZE")); 366 | | // @dev key for when funding was last updated at 367 | * | bytes32 internal constant FUNDING_UPDATED_AT = keccak256(abi.encode("FUNDING_UPDATED_AT")); 368 | | // @dev key for claimable funding amount 369 | * | bytes32 internal constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT")); 370 | | // @dev key for claimable collateral amount 371 | * | bytes32 internal constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMABLE_COLLATERAL_AMOUNT")); 372 | | // @dev key for claimable collateral factor 373 | | bytes32 internal constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_FACTOR")); 374 | | // @dev key for claimable collateral time divisor 375 | | bytes32 internal constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_TIME_DIVISOR")); 376 | | // @dev key for claimed collateral amount 377 | | bytes32 internal constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMED_COLLATERAL_AMOUNT")); 378 | | // @dev key for optimal usage factor 379 | * | bytes32 internal constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode("OPTIMAL_USAGE_FACTOR")); 380 | | // @dev key for base borrowing factor 381 | | bytes32 internal constant BASE_BORROWING_FACTOR = keccak256(abi.encode("BASE_BORROWING_FACTOR")); 382 | | // @dev key for above optimal usage borrowing factor 383 | | bytes32 internal constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode("ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR")); 384 | | // @dev key for borrowing factor 385 | * | bytes32 internal constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR")); 386 | | // @dev key for borrowing factor 387 | * | bytes32 internal constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode("BORROWING_EXPONENT_FACTOR")); 388 | | // @dev key for skipping the borrowing factor for the smaller side 389 | * | bytes32 internal constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode("SKIP_BORROWING_FEE_FOR_SMALLER_SIDE")); 390 | | // @dev key for cumulative borrowing factor 391 | * | bytes32 internal constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR")); 392 | | // @dev key for when the cumulative borrowing factor was last updated at 393 | * | bytes32 internal constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR_UPDATED_AT")); 394 | | // @dev key for total borrowing amount 395 | * | bytes32 internal constant TOTAL_BORROWING = keccak256(abi.encode("TOTAL_BORROWING")); 396 | | // @dev key for affiliate reward 397 | * | bytes32 internal constant AFFILIATE_REWARD = keccak256(abi.encode("AFFILIATE_REWARD")); 398 | | // @dev key for max allowed subaccount action count 399 | | bytes32 internal constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT")); 400 | | // @dev key for subaccount action count 401 | | bytes32 internal constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("SUBACCOUNT_ACTION_COUNT")); 402 | | // @dev key for subaccount auto top up amount 403 | | bytes32 internal constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode("SUBACCOUNT_AUTO_TOP_UP_AMOUNT")); 404 | | // @dev key for subaccount order action 405 | | bytes32 internal constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode("SUBACCOUNT_ORDER_ACTION")); 406 | | // @dev key for fee distributor swap order token index 407 | | bytes32 internal constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX")); 408 | | // @dev key for fee distributor swap fee batch 409 | | bytes32 internal constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_FEE_BATCH")); 410 | | 411 | | // @dev key for the glv pending shift 412 | | bytes32 internal constant GLV_PENDING_SHIFT = keccak256(abi.encode("GLV_PENDING_SHIFT")); 413 | | bytes32 internal constant GLV_PENDING_SHIFT_BACKREF = keccak256(abi.encode("GLV_PENDING_SHIFT_BACKREF")); 414 | | // @dev key for the max market token balance usd for glv 415 | | bytes32 internal constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode("GLV_MAX_MARKET_TOKEN_BALANCE_USD")); 416 | | // @dev key for is glv market disabled 417 | | bytes32 internal constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode("IS_GLV_MARKET_DISABLED")); 418 | | 419 | | // @dev constant for user initiated cancel reason 420 | | string internal constant USER_INITIATED_CANCEL = "USER_INITIATED_CANCEL"; 421 | | 422 | | // @dev key for the account deposit list 423 | | // @param account the account for the list 424 | * | function accountDepositListKey(address account) internal pure returns (bytes32) { 425 | * | return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account)); 426 | | } 427 | | 428 | | // @dev key for the account withdrawal list 429 | | // @param account the account for the list 430 | * | function accountWithdrawalListKey(address account) internal pure returns (bytes32) { 431 | * | return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account)); 432 | | } 433 | | 434 | | // @dev key for the account shift list 435 | | // @param account the account for the list 436 | | function accountShiftListKey(address account) internal pure returns (bytes32) { 437 | | return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account)); 438 | | } 439 | | 440 | | // @dev key for the account glv deposit list 441 | | // @param account the account for the list 442 | | function accountGlvDepositListKey(address account) internal pure returns (bytes32) { 443 | | return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account)); 444 | | } 445 | | 446 | | // @dev key for the glv supported market list 447 | | // @param glv the glv for the supported market list 448 | | function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) { 449 | | return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv)); 450 | | } 451 | | 452 | | // @dev key for the account position list 453 | | // @param account the account for the list 454 | * | function accountPositionListKey(address account) internal pure returns (bytes32) { 455 | * | return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account)); 456 | | } 457 | | 458 | | // @dev key for the account order list 459 | | // @param account the account for the list 460 | * | function accountOrderListKey(address account) internal pure returns (bytes32) { 461 | * | return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account)); 462 | | } 463 | | 464 | | // @dev key for the subaccount list 465 | | // @param account the account for the list 466 | | function subaccountListKey(address account) internal pure returns (bytes32) { 467 | | return keccak256(abi.encode(SUBACCOUNT_LIST, account)); 468 | | } 469 | | 470 | | // @dev key for the auto cancel order list 471 | | // @param position key the position key for the list 472 | * | function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) { 473 | * | return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey)); 474 | | } 475 | | 476 | | // @dev key for the claimable fee amount 477 | | // @param market the market for the fee 478 | | // @param token the token for the fee 479 | * | function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) { 480 | * | return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token)); 481 | | } 482 | | 483 | | // @dev key for the claimable ui fee amount 484 | | // @param market the market for the fee 485 | | // @param token the token for the fee 486 | | // @param account the account that can claim the ui fee 487 | * | function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) { 488 | * | return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token)); 489 | | } 490 | | 491 | | // @dev key for the claimable ui fee amount for account 492 | | // @param market the market for the fee 493 | | // @param token the token for the fee 494 | | // @param account the account that can claim the ui fee 495 | | function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) { 496 | | return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account)); 497 | | } 498 | | 499 | | // @dev key for deposit gas limit 500 | | // @param singleToken whether a single token or pair tokens are being deposited 501 | | // @return key for deposit gas limit 502 | * | function depositGasLimitKey(bool singleToken) internal pure returns (bytes32) { 503 | * | return keccak256(abi.encode( 504 | | DEPOSIT_GAS_LIMIT, 505 | * | singleToken 506 | | )); 507 | | } 508 | | 509 | | // @dev key for withdrawal gas limit 510 | | // @return key for withdrawal gas limit 511 | * | function withdrawalGasLimitKey() internal pure returns (bytes32) { 512 | * | return WITHDRAWAL_GAS_LIMIT; 513 | | } 514 | | 515 | | // @dev key for shift gas limit 516 | | // @return key for shift gas limit 517 | | function shiftGasLimitKey() internal pure returns (bytes32) { 518 | | return SHIFT_GAS_LIMIT; 519 | | } 520 | | 521 | | function glvDepositGasLimitKey() internal pure returns (bytes32) { 522 | | return GLV_DEPOSIT_GAS_LIMIT; 523 | | } 524 | | 525 | | function glvPerMarketGasLimitKey() internal pure returns (bytes32) { 526 | | return GLV_PER_MARKET_GAS_LIMIT; 527 | | } 528 | | 529 | | // @dev key for single swap gas limit 530 | | // @return key for single swap gas limit 531 | * | function singleSwapGasLimitKey() internal pure returns (bytes32) { 532 | * | return SINGLE_SWAP_GAS_LIMIT; 533 | | } 534 | | 535 | | // @dev key for increase order gas limit 536 | | // @return key for increase order gas limit 537 | * | function increaseOrderGasLimitKey() internal pure returns (bytes32) { 538 | * | return INCREASE_ORDER_GAS_LIMIT; 539 | | } 540 | | 541 | | // @dev key for decrease order gas limit 542 | | // @return key for decrease order gas limit 543 | * | function decreaseOrderGasLimitKey() internal pure returns (bytes32) { 544 | * | return DECREASE_ORDER_GAS_LIMIT; 545 | | } 546 | | 547 | | // @dev key for swap order gas limit 548 | | // @return key for swap order gas limit 549 | * | function swapOrderGasLimitKey() internal pure returns (bytes32) { 550 | * | return SWAP_ORDER_GAS_LIMIT; 551 | | } 552 | | 553 | * | function swapPathMarketFlagKey(address market) internal pure returns (bytes32) { 554 | * | return keccak256(abi.encode( 555 | | SWAP_PATH_MARKET_FLAG, 556 | * | market 557 | | )); 558 | | } 559 | | 560 | | // @dev key for whether create glv deposit is disabled 561 | | // @param the create deposit module 562 | | // @return key for whether create deposit is disabled 563 | | function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 564 | | return keccak256(abi.encode( 565 | | CREATE_GLV_DEPOSIT_FEATURE_DISABLED, 566 | | module 567 | | )); 568 | | } 569 | | 570 | | // @dev key for whether cancel glv deposit is disabled 571 | | // @param the cancel deposit module 572 | | // @return key for whether cancel deposit is disabled 573 | | function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 574 | | return keccak256(abi.encode( 575 | | CANCEL_GLV_DEPOSIT_FEATURE_DISABLED, 576 | | module 577 | | )); 578 | | } 579 | | 580 | | // @dev key for whether execute glv deposit is disabled 581 | | // @param the execute deposit module 582 | | // @return key for whether execute deposit is disabled 583 | | function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 584 | | return keccak256(abi.encode( 585 | | EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED, 586 | | module 587 | | )); 588 | | } 589 | | 590 | | // @dev key for whether shift deposit is disabled 591 | | // @param the execute deposit module 592 | | // @return key for whether execute deposit is disabled 593 | | function glvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) { 594 | | return keccak256(abi.encode( 595 | | GLV_SHIFT_FEATURE_DISABLED, 596 | | module 597 | | )); 598 | | } 599 | | 600 | | 601 | | // @dev key for whether create deposit is disabled 602 | | // @param the create deposit module 603 | | // @return key for whether create deposit is disabled 604 | * | function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 605 | * | return keccak256(abi.encode( 606 | | CREATE_DEPOSIT_FEATURE_DISABLED, 607 | * | module 608 | | )); 609 | | } 610 | | 611 | | // @dev key for whether cancel deposit is disabled 612 | | // @param the cancel deposit module 613 | | // @return key for whether cancel deposit is disabled 614 | * | function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 615 | * | return keccak256(abi.encode( 616 | | CANCEL_DEPOSIT_FEATURE_DISABLED, 617 | * | module 618 | | )); 619 | | } 620 | | 621 | | // @dev key for whether execute deposit is disabled 622 | | // @param the execute deposit module 623 | | // @return key for whether execute deposit is disabled 624 | * | function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) { 625 | * | return keccak256(abi.encode( 626 | | EXECUTE_DEPOSIT_FEATURE_DISABLED, 627 | * | module 628 | | )); 629 | | } 630 | | 631 | | // @dev key for whether create withdrawal is disabled 632 | | // @param the create withdrawal module 633 | | // @return key for whether create withdrawal is disabled 634 | * | function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) { 635 | * | return keccak256(abi.encode( 636 | | CREATE_WITHDRAWAL_FEATURE_DISABLED, 637 | * | module 638 | | )); 639 | | } 640 | | 641 | | // @dev key for whether cancel withdrawal is disabled 642 | | // @param the cancel withdrawal module 643 | | // @return key for whether cancel withdrawal is disabled 644 | * | function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) { 645 | * | return keccak256(abi.encode( 646 | | CANCEL_WITHDRAWAL_FEATURE_DISABLED, 647 | * | module 648 | | )); 649 | | } 650 | | 651 | | // @dev key for whether execute withdrawal is disabled 652 | | // @param the execute withdrawal module 653 | | // @return key for whether execute withdrawal is disabled 654 | * | function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) { 655 | * | return keccak256(abi.encode( 656 | | EXECUTE_WITHDRAWAL_FEATURE_DISABLED, 657 | * | module 658 | | )); 659 | | } 660 | | 661 | | // @dev key for whether execute atomic withdrawal is disabled 662 | | // @param the execute atomic withdrawal module 663 | | // @return key for whether execute atomic withdrawal is disabled 664 | * | function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) { 665 | * | return keccak256(abi.encode( 666 | | EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED, 667 | * | module 668 | | )); 669 | | } 670 | | 671 | | // @dev key for whether create shift is disabled 672 | | // @param the create shift module 673 | | // @return key for whether create shift is disabled 674 | | function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) { 675 | | return keccak256(abi.encode( 676 | | CREATE_SHIFT_FEATURE_DISABLED, 677 | | module 678 | | )); 679 | | } 680 | | 681 | | // @dev key for whether cancel shift is disabled 682 | | // @param the cancel shift module 683 | | // @return key for whether cancel shift is disabled 684 | | function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) { 685 | | return keccak256(abi.encode( 686 | | CANCEL_SHIFT_FEATURE_DISABLED, 687 | | module 688 | | )); 689 | | } 690 | | 691 | | // @dev key for whether execute shift is disabled 692 | | // @param the execute shift module 693 | | // @return key for whether execute shift is disabled 694 | | function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) { 695 | | return keccak256(abi.encode( 696 | | EXECUTE_SHIFT_FEATURE_DISABLED, 697 | | module 698 | | )); 699 | | } 700 | | 701 | | // @dev key for whether create order is disabled 702 | | // @param the create order module 703 | | // @return key for whether create order is disabled 704 | * | function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) { 705 | * | return keccak256(abi.encode( 706 | | CREATE_ORDER_FEATURE_DISABLED, 707 | * | module, 708 | * | orderType 709 | | )); 710 | | } 711 | | 712 | | // @dev key for whether execute order is disabled 713 | | // @param the execute order module 714 | | // @return key for whether execute order is disabled 715 | * | function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) { 716 | * | return keccak256(abi.encode( 717 | | EXECUTE_ORDER_FEATURE_DISABLED, 718 | * | module, 719 | * | orderType 720 | | )); 721 | | } 722 | | 723 | | // @dev key for whether execute adl is disabled 724 | | // @param the execute adl module 725 | | // @return key for whether execute adl is disabled 726 | * | function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) { 727 | * | return keccak256(abi.encode( 728 | | EXECUTE_ADL_FEATURE_DISABLED, 729 | * | module, 730 | * | orderType 731 | | )); 732 | | } 733 | | 734 | | // @dev key for whether update order is disabled 735 | | // @param the update order module 736 | | // @return key for whether update order is disabled 737 | | function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) { 738 | | return keccak256(abi.encode( 739 | | UPDATE_ORDER_FEATURE_DISABLED, 740 | | module, 741 | | orderType 742 | | )); 743 | | } 744 | | 745 | | // @dev key for whether cancel order is disabled 746 | | // @param the cancel order module 747 | | // @return key for whether cancel order is disabled 748 | * | function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) { 749 | * | return keccak256(abi.encode( 750 | | CANCEL_ORDER_FEATURE_DISABLED, 751 | * | module, 752 | * | orderType 753 | | )); 754 | | } 755 | | 756 | | // @dev key for whether claim funding fees is disabled 757 | | // @param the claim funding fees module 758 | * | function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) { 759 | * | return keccak256(abi.encode( 760 | | CLAIM_FUNDING_FEES_FEATURE_DISABLED, 761 | * | module 762 | | )); 763 | | } 764 | | 765 | | // @dev key for whether claim colltareral is disabled 766 | | // @param the claim funding fees module 767 | | function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) { 768 | | return keccak256(abi.encode( 769 | | CLAIM_COLLATERAL_FEATURE_DISABLED, 770 | | module 771 | | )); 772 | | } 773 | | 774 | | // @dev key for whether claim affiliate rewards is disabled 775 | | // @param the claim affiliate rewards module 776 | | function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) { 777 | | return keccak256(abi.encode( 778 | | CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED, 779 | | module 780 | | )); 781 | | } 782 | | 783 | | // @dev key for whether claim ui fees is disabled 784 | | // @param the claim ui fees module 785 | | function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) { 786 | | return keccak256(abi.encode( 787 | | CLAIM_UI_FEES_FEATURE_DISABLED, 788 | | module 789 | | )); 790 | | } 791 | | 792 | | // @dev key for whether subaccounts are disabled 793 | | // @param the subaccount module 794 | | function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) { 795 | | return keccak256(abi.encode( 796 | | SUBACCOUNT_FEATURE_DISABLED, 797 | | module 798 | | )); 799 | | } 800 | | 801 | | // @dev key for ui fee factor 802 | | // @param account the fee receiver account 803 | | // @return key for ui fee factor 804 | * | function uiFeeFactorKey(address account) internal pure returns (bytes32) { 805 | * | return keccak256(abi.encode( 806 | | UI_FEE_FACTOR, 807 | * | account 808 | | )); 809 | | } 810 | | 811 | | // @dev key for whether an oracle provider is enabled 812 | | // @param provider the oracle provider 813 | | // @return key for whether an oracle provider is enabled 814 | * | function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) { 815 | * | return keccak256(abi.encode( 816 | | IS_ORACLE_PROVIDER_ENABLED, 817 | * | provider 818 | | )); 819 | | } 820 | | 821 | | // @dev key for whether an oracle provider is allowed to be used for atomic actions 822 | | // @param provider the oracle provider 823 | | // @return key for whether an oracle provider is allowed to be used for atomic actions 824 | * | function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) { 825 | * | return keccak256(abi.encode( 826 | | IS_ATOMIC_ORACLE_PROVIDER, 827 | * | provider 828 | | )); 829 | | } 830 | | 831 | | // @dev key for oracle timestamp adjustment 832 | | // @param provider the oracle provider 833 | | // @param token the token 834 | | // @return key for oracle timestamp adjustment 835 | | function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) { 836 | | return keccak256(abi.encode( 837 | | ORACLE_TIMESTAMP_ADJUSTMENT, 838 | | provider, 839 | | token 840 | | )); 841 | | } 842 | | 843 | | // @dev key for oracle provider for token 844 | | // @param token the token 845 | | // @return key for oracle provider for token 846 | * | function oracleProviderForTokenKey(address token) internal pure returns (bytes32) { 847 | * | return keccak256(abi.encode( 848 | | ORACLE_PROVIDER_FOR_TOKEN, 849 | * | token 850 | | )); 851 | | } 852 | | 853 | | // @dev key for gas to forward for token transfer 854 | | // @param the token to check 855 | | // @return key for gas to forward for token transfer 856 | * | function tokenTransferGasLimit(address token) internal pure returns (bytes32) { 857 | * | return keccak256(abi.encode( 858 | | TOKEN_TRANSFER_GAS_LIMIT, 859 | * | token 860 | | )); 861 | | } 862 | | 863 | | // @dev the default callback contract 864 | | // @param account the user's account 865 | | // @param market the address of the market 866 | | // @param callbackContract the callback contract 867 | * | function savedCallbackContract(address account, address market) internal pure returns (bytes32) { 868 | * | return keccak256(abi.encode( 869 | | SAVED_CALLBACK_CONTRACT, 870 | * | account, 871 | * | market 872 | | )); 873 | | } 874 | | 875 | | // @dev the min collateral factor key 876 | | // @param the market for the min collateral factor 877 | * | function minCollateralFactorKey(address market) internal pure returns (bytes32) { 878 | * | return keccak256(abi.encode( 879 | | MIN_COLLATERAL_FACTOR, 880 | * | market 881 | | )); 882 | | } 883 | | 884 | | // @dev the min collateral factor for open interest multiplier key 885 | | // @param the market for the factor 886 | * | function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) { 887 | * | return keccak256(abi.encode( 888 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER, 889 | * | market, 890 | * | isLong 891 | | )); 892 | | } 893 | | 894 | | // @dev the key for the virtual token id 895 | | // @param the token to get the virtual id for 896 | * | function virtualTokenIdKey(address token) internal pure returns (bytes32) { 897 | * | return keccak256(abi.encode( 898 | | VIRTUAL_TOKEN_ID, 899 | * | token 900 | | )); 901 | | } 902 | | 903 | | // @dev the key for the virtual market id 904 | | // @param the market to get the virtual id for 905 | * | function virtualMarketIdKey(address market) internal pure returns (bytes32) { 906 | * | return keccak256(abi.encode( 907 | | VIRTUAL_MARKET_ID, 908 | * | market 909 | | )); 910 | | } 911 | | 912 | | // @dev the key for the virtual inventory for positions 913 | | // @param the virtualTokenId the virtual token id 914 | | function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) { 915 | | return keccak256(abi.encode( 916 | | VIRTUAL_INVENTORY_FOR_POSITIONS, 917 | | virtualTokenId 918 | | )); 919 | | } 920 | | 921 | | // @dev the key for the virtual inventory for swaps 922 | | // @param the virtualMarketId the virtual market id 923 | | // @param the token to check the inventory for 924 | | function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) { 925 | | return keccak256(abi.encode( 926 | | VIRTUAL_INVENTORY_FOR_SWAPS, 927 | | virtualMarketId, 928 | | isLongToken 929 | | )); 930 | | } 931 | | 932 | | // @dev key for position impact factor 933 | | // @param market the market address to check 934 | | // @param isPositive whether the impact is positive or negative 935 | | // @return key for position impact factor 936 | * | function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) { 937 | * | return keccak256(abi.encode( 938 | | POSITION_IMPACT_FACTOR, 939 | * | market, 940 | * | isPositive 941 | | )); 942 | | } 943 | | 944 | | // @dev key for position impact exponent factor 945 | | // @param market the market address to check 946 | | // @return key for position impact exponent factor 947 | * | function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) { 948 | * | return keccak256(abi.encode( 949 | | POSITION_IMPACT_EXPONENT_FACTOR, 950 | * | market 951 | | )); 952 | | } 953 | | 954 | | // @dev key for the max position impact factor 955 | | // @param market the market address to check 956 | | // @return key for the max position impact factor 957 | * | function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) { 958 | * | return keccak256(abi.encode( 959 | | MAX_POSITION_IMPACT_FACTOR, 960 | * | market, 961 | * | isPositive 962 | | )); 963 | | } 964 | | 965 | | // @dev key for the max position impact factor for liquidations 966 | | // @param market the market address to check 967 | | // @return key for the max position impact factor 968 | | function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) { 969 | | return keccak256(abi.encode( 970 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS, 971 | | market 972 | | )); 973 | | } 974 | | 975 | | // @dev key for position fee factor 976 | | // @param market the market address to check 977 | | // @param forPositiveImpact whether the fee is for an action that has a positive price impact 978 | | // @return key for position fee factor 979 | * | function positionFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) { 980 | * | return keccak256(abi.encode( 981 | | POSITION_FEE_FACTOR, 982 | * | market, 983 | * | forPositiveImpact 984 | | )); 985 | | } 986 | | 987 | | // @dev key for swap impact factor 988 | | // @param market the market address to check 989 | | // @param isPositive whether the impact is positive or negative 990 | | // @return key for swap impact factor 991 | * | function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) { 992 | * | return keccak256(abi.encode( 993 | | SWAP_IMPACT_FACTOR, 994 | * | market, 995 | * | isPositive 996 | | )); 997 | | } 998 | | 999 | | // @dev key for swap impact exponent factor 1000 | | // @param market the market address to check 1001 | | // @return key for swap impact exponent factor 1002 | * | function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) { 1003 | * | return keccak256(abi.encode( 1004 | | SWAP_IMPACT_EXPONENT_FACTOR, 1005 | * | market 1006 | | )); 1007 | | } 1008 | | 1009 | | 1010 | | // @dev key for swap fee factor 1011 | | // @param market the market address to check 1012 | | // @return key for swap fee factor 1013 | * | function swapFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) { 1014 | * | return keccak256(abi.encode( 1015 | | SWAP_FEE_FACTOR, 1016 | * | market, 1017 | * | forPositiveImpact 1018 | | )); 1019 | | } 1020 | | 1021 | | // @dev key for atomic swap fee factor 1022 | | // @param market the market address to check 1023 | | // @return key for atomic swap fee factor 1024 | * | function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) { 1025 | * | return keccak256(abi.encode( 1026 | | ATOMIC_SWAP_FEE_FACTOR, 1027 | * | market 1028 | | )); 1029 | | } 1030 | | 1031 | | // @dev key for oracle type 1032 | | // @param token the token to check 1033 | | // @return key for oracle type 1034 | | function oracleTypeKey(address token) internal pure returns (bytes32) { 1035 | | return keccak256(abi.encode( 1036 | | ORACLE_TYPE, 1037 | | token 1038 | | )); 1039 | | } 1040 | | 1041 | | // @dev key for open interest 1042 | | // @param market the market to check 1043 | | // @param collateralToken the collateralToken to check 1044 | | // @param isLong whether to check the long or short open interest 1045 | | // @return key for open interest 1046 | * | function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 1047 | * | return keccak256(abi.encode( 1048 | | OPEN_INTEREST, 1049 | * | market, 1050 | * | collateralToken, 1051 | * | isLong 1052 | | )); 1053 | | } 1054 | | 1055 | | // @dev key for open interest in tokens 1056 | | // @param market the market to check 1057 | | // @param collateralToken the collateralToken to check 1058 | | // @param isLong whether to check the long or short open interest 1059 | | // @return key for open interest in tokens 1060 | * | function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 1061 | * | return keccak256(abi.encode( 1062 | | OPEN_INTEREST_IN_TOKENS, 1063 | * | market, 1064 | * | collateralToken, 1065 | * | isLong 1066 | | )); 1067 | | } 1068 | | 1069 | | // @dev key for collateral sum for a market 1070 | | // @param market the market to check 1071 | | // @param collateralToken the collateralToken to check 1072 | | // @param isLong whether to check the long or short open interest 1073 | | // @return key for collateral sum 1074 | * | function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 1075 | * | return keccak256(abi.encode( 1076 | | COLLATERAL_SUM, 1077 | * | market, 1078 | * | collateralToken, 1079 | * | isLong 1080 | | )); 1081 | | } 1082 | | 1083 | | // @dev key for amount of tokens in a market's pool 1084 | | // @param market the market to check 1085 | | // @param token the token to check 1086 | | // @return key for amount of tokens in a market's pool 1087 | * | function poolAmountKey(address market, address token) internal pure returns (bytes32) { 1088 | * | return keccak256(abi.encode( 1089 | | POOL_AMOUNT, 1090 | * | market, 1091 | * | token 1092 | | )); 1093 | | } 1094 | | 1095 | | // @dev the key for the max amount of pool tokens 1096 | | // @param market the market for the pool 1097 | | // @param token the token for the pool 1098 | * | function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) { 1099 | * | return keccak256(abi.encode( 1100 | | MAX_POOL_AMOUNT, 1101 | * | market, 1102 | * | token 1103 | | )); 1104 | | } 1105 | | 1106 | | // @dev the key for the max usd of pool tokens for deposits 1107 | | // @param market the market for the pool 1108 | | // @param token the token for the pool 1109 | * | function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) { 1110 | * | return keccak256(abi.encode( 1111 | | MAX_POOL_USD_FOR_DEPOSIT, 1112 | * | market, 1113 | * | token 1114 | | )); 1115 | | } 1116 | | 1117 | | // @dev the key for the max open interest 1118 | | // @param market the market for the pool 1119 | | // @param isLong whether the key is for the long or short side 1120 | * | function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) { 1121 | * | return keccak256(abi.encode( 1122 | | MAX_OPEN_INTEREST, 1123 | * | market, 1124 | * | isLong 1125 | | )); 1126 | | } 1127 | | 1128 | | // @dev key for amount of tokens in a market's position impact pool 1129 | | // @param market the market to check 1130 | | // @return key for amount of tokens in a market's position impact pool 1131 | * | function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) { 1132 | * | return keccak256(abi.encode( 1133 | | POSITION_IMPACT_POOL_AMOUNT, 1134 | * | market 1135 | | )); 1136 | | } 1137 | | 1138 | | // @dev key for min amount of tokens in a market's position impact pool 1139 | | // @param market the market to check 1140 | | // @return key for min amount of tokens in a market's position impact pool 1141 | | function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) { 1142 | | return keccak256(abi.encode( 1143 | | MIN_POSITION_IMPACT_POOL_AMOUNT, 1144 | | market 1145 | | )); 1146 | | } 1147 | | 1148 | | // @dev key for position impact pool distribution rate 1149 | | // @param market the market to check 1150 | | // @return key for position impact pool distribution rate 1151 | * | function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) { 1152 | * | return keccak256(abi.encode( 1153 | | POSITION_IMPACT_POOL_DISTRIBUTION_RATE, 1154 | * | market 1155 | | )); 1156 | | } 1157 | | 1158 | | // @dev key for position impact pool distributed at 1159 | | // @param market the market to check 1160 | | // @return key for position impact pool distributed at 1161 | * | function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) { 1162 | * | return keccak256(abi.encode( 1163 | | POSITION_IMPACT_POOL_DISTRIBUTED_AT, 1164 | * | market 1165 | | )); 1166 | | } 1167 | | 1168 | | // @dev key for amount of tokens in a market's swap impact pool 1169 | | // @param market the market to check 1170 | | // @param token the token to check 1171 | | // @return key for amount of tokens in a market's swap impact pool 1172 | * | function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) { 1173 | * | return keccak256(abi.encode( 1174 | | SWAP_IMPACT_POOL_AMOUNT, 1175 | * | market, 1176 | * | token 1177 | | )); 1178 | | } 1179 | | 1180 | | // @dev key for reserve factor 1181 | | // @param market the market to check 1182 | | // @param isLong whether to get the key for the long or short side 1183 | | // @return key for reserve factor 1184 | * | function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1185 | * | return keccak256(abi.encode( 1186 | | RESERVE_FACTOR, 1187 | * | market, 1188 | * | isLong 1189 | | )); 1190 | | } 1191 | | 1192 | | // @dev key for open interest reserve factor 1193 | | // @param market the market to check 1194 | | // @param isLong whether to get the key for the long or short side 1195 | | // @return key for open interest reserve factor 1196 | * | function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1197 | * | return keccak256(abi.encode( 1198 | | OPEN_INTEREST_RESERVE_FACTOR, 1199 | * | market, 1200 | * | isLong 1201 | | )); 1202 | | } 1203 | | 1204 | | // @dev key for max pnl factor 1205 | | // @param market the market to check 1206 | | // @param isLong whether to get the key for the long or short side 1207 | | // @return key for max pnl factor 1208 | * | function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) { 1209 | * | return keccak256(abi.encode( 1210 | | MAX_PNL_FACTOR, 1211 | * | pnlFactorType, 1212 | * | market, 1213 | * | isLong 1214 | | )); 1215 | | } 1216 | | 1217 | | // @dev the key for min PnL factor after ADL 1218 | | // @param market the market for the pool 1219 | | // @param isLong whether the key is for the long or short side 1220 | * | function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) { 1221 | * | return keccak256(abi.encode( 1222 | | MIN_PNL_FACTOR_AFTER_ADL, 1223 | * | market, 1224 | * | isLong 1225 | | )); 1226 | | } 1227 | | 1228 | | // @dev key for latest adl time 1229 | | // @param market the market to check 1230 | | // @param isLong whether to get the key for the long or short side 1231 | | // @return key for latest adl time 1232 | * | function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) { 1233 | * | return keccak256(abi.encode( 1234 | | LATEST_ADL_AT, 1235 | * | market, 1236 | * | isLong 1237 | | )); 1238 | | } 1239 | | 1240 | | // @dev key for whether adl is enabled 1241 | | // @param market the market to check 1242 | | // @param isLong whether to get the key for the long or short side 1243 | | // @return key for whether adl is enabled 1244 | * | function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) { 1245 | * | return keccak256(abi.encode( 1246 | | IS_ADL_ENABLED, 1247 | * | market, 1248 | * | isLong 1249 | | )); 1250 | | } 1251 | | 1252 | | // @dev key for funding factor 1253 | | // @param market the market to check 1254 | | // @return key for funding factor 1255 | * | function fundingFactorKey(address market) internal pure returns (bytes32) { 1256 | * | return keccak256(abi.encode( 1257 | | FUNDING_FACTOR, 1258 | * | market 1259 | | )); 1260 | | } 1261 | | 1262 | | // @dev the key for funding exponent 1263 | | // @param market the market for the pool 1264 | * | function fundingExponentFactorKey(address market) internal pure returns (bytes32) { 1265 | * | return keccak256(abi.encode( 1266 | | FUNDING_EXPONENT_FACTOR, 1267 | * | market 1268 | | )); 1269 | | } 1270 | | 1271 | | // @dev the key for saved funding factor 1272 | | // @param market the market for the pool 1273 | * | function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) { 1274 | * | return keccak256(abi.encode( 1275 | | SAVED_FUNDING_FACTOR_PER_SECOND, 1276 | * | market 1277 | | )); 1278 | | } 1279 | | 1280 | | // @dev the key for funding increase factor 1281 | | // @param market the market for the pool 1282 | * | function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) { 1283 | * | return keccak256(abi.encode( 1284 | | FUNDING_INCREASE_FACTOR_PER_SECOND, 1285 | * | market 1286 | | )); 1287 | | } 1288 | | 1289 | | // @dev the key for funding decrease factor 1290 | | // @param market the market for the pool 1291 | | function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) { 1292 | | return keccak256(abi.encode( 1293 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1294 | | market 1295 | | )); 1296 | | } 1297 | | 1298 | | // @dev the key for min funding factor 1299 | | // @param market the market for the pool 1300 | | function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) { 1301 | | return keccak256(abi.encode( 1302 | | MIN_FUNDING_FACTOR_PER_SECOND, 1303 | | market 1304 | | )); 1305 | | } 1306 | | 1307 | | // @dev the key for max funding factor 1308 | | // @param market the market for the pool 1309 | * | function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) { 1310 | * | return keccak256(abi.encode( 1311 | | MAX_FUNDING_FACTOR_PER_SECOND, 1312 | * | market 1313 | | )); 1314 | | } 1315 | | 1316 | | // @dev the key for threshold for stable funding 1317 | | // @param market the market for the pool 1318 | | function thresholdForStableFundingKey(address market) internal pure returns (bytes32) { 1319 | | return keccak256(abi.encode( 1320 | | THRESHOLD_FOR_STABLE_FUNDING, 1321 | | market 1322 | | )); 1323 | | } 1324 | | 1325 | | // @dev the key for threshold for decreasing funding 1326 | | // @param market the market for the pool 1327 | | function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) { 1328 | | return keccak256(abi.encode( 1329 | | THRESHOLD_FOR_DECREASE_FUNDING, 1330 | | market 1331 | | )); 1332 | | } 1333 | | 1334 | | // @dev key for funding fee amount per size 1335 | | // @param market the market to check 1336 | | // @param collateralToken the collateralToken to get the key for 1337 | | // @param isLong whether to get the key for the long or short side 1338 | | // @return key for funding fee amount per size 1339 | * | function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 1340 | * | return keccak256(abi.encode( 1341 | | FUNDING_FEE_AMOUNT_PER_SIZE, 1342 | * | market, 1343 | * | collateralToken, 1344 | * | isLong 1345 | | )); 1346 | | } 1347 | | 1348 | | // @dev key for claimabel funding amount per size 1349 | | // @param market the market to check 1350 | | // @param collateralToken the collateralToken to get the key for 1351 | | // @param isLong whether to get the key for the long or short side 1352 | | // @return key for claimable funding amount per size 1353 | * | function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) { 1354 | * | return keccak256(abi.encode( 1355 | | CLAIMABLE_FUNDING_AMOUNT_PER_SIZE, 1356 | * | market, 1357 | * | collateralToken, 1358 | * | isLong 1359 | | )); 1360 | | } 1361 | | 1362 | | // @dev key for when funding was last updated 1363 | | // @param market the market to check 1364 | | // @return key for when funding was last updated 1365 | * | function fundingUpdatedAtKey(address market) internal pure returns (bytes32) { 1366 | * | return keccak256(abi.encode( 1367 | | FUNDING_UPDATED_AT, 1368 | * | market 1369 | | )); 1370 | | } 1371 | | 1372 | | // @dev key for claimable funding amount 1373 | | // @param market the market to check 1374 | | // @param token the token to check 1375 | | // @return key for claimable funding amount 1376 | * | function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) { 1377 | * | return keccak256(abi.encode( 1378 | | CLAIMABLE_FUNDING_AMOUNT, 1379 | * | market, 1380 | * | token 1381 | | )); 1382 | | } 1383 | | 1384 | | // @dev key for claimable funding amount by account 1385 | | // @param market the market to check 1386 | | // @param token the token to check 1387 | | // @param account the account to check 1388 | | // @return key for claimable funding amount 1389 | * | function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) { 1390 | * | return keccak256(abi.encode( 1391 | | CLAIMABLE_FUNDING_AMOUNT, 1392 | * | market, 1393 | * | token, 1394 | * | account 1395 | | )); 1396 | | } 1397 | | 1398 | | // @dev key for claimable collateral amount 1399 | | // @param market the market to check 1400 | | // @param token the token to check 1401 | | // @param account the account to check 1402 | | // @param timeKey the time key for the claimable amount 1403 | | // @return key for claimable funding amount 1404 | * | function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) { 1405 | * | return keccak256(abi.encode( 1406 | | CLAIMABLE_COLLATERAL_AMOUNT, 1407 | * | market, 1408 | * | token 1409 | | )); 1410 | | } 1411 | | 1412 | | // @dev key for claimable collateral amount for a timeKey for an account 1413 | | // @param market the market to check 1414 | | // @param token the token to check 1415 | | // @param account the account to check 1416 | | // @param timeKey the time key for the claimable amount 1417 | | // @return key for claimable funding amount 1418 | | function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) { 1419 | | return keccak256(abi.encode( 1420 | | CLAIMABLE_COLLATERAL_AMOUNT, 1421 | | market, 1422 | | token, 1423 | | timeKey, 1424 | | account 1425 | | )); 1426 | | } 1427 | | 1428 | | // @dev key for claimable collateral factor for a timeKey 1429 | | // @param market the market to check 1430 | | // @param token the token to check 1431 | | // @param timeKey the time key for the claimable amount 1432 | | // @return key for claimable funding amount 1433 | | function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) { 1434 | | return keccak256(abi.encode( 1435 | | CLAIMABLE_COLLATERAL_FACTOR, 1436 | | market, 1437 | | token, 1438 | | timeKey 1439 | | )); 1440 | | } 1441 | | 1442 | | // @dev key for claimable collateral factor for a timeKey for an account 1443 | | // @param market the market to check 1444 | | // @param token the token to check 1445 | | // @param timeKey the time key for the claimable amount 1446 | | // @param account the account to check 1447 | | // @return key for claimable funding amount 1448 | | function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) { 1449 | | return keccak256(abi.encode( 1450 | | CLAIMABLE_COLLATERAL_FACTOR, 1451 | | market, 1452 | | token, 1453 | | timeKey, 1454 | | account 1455 | | )); 1456 | | } 1457 | | 1458 | | // @dev key for claimable collateral factor 1459 | | // @param market the market to check 1460 | | // @param token the token to check 1461 | | // @param account the account to check 1462 | | // @param timeKey the time key for the claimable amount 1463 | | // @return key for claimable funding amount 1464 | | function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) { 1465 | | return keccak256(abi.encode( 1466 | | CLAIMED_COLLATERAL_AMOUNT, 1467 | | market, 1468 | | token, 1469 | | timeKey, 1470 | | account 1471 | | )); 1472 | | } 1473 | | 1474 | | // @dev key for optimal usage factor 1475 | | // @param market the market to check 1476 | | // @param isLong whether to get the key for the long or short side 1477 | | // @return key for optimal usage factor 1478 | * | function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1479 | * | return keccak256(abi.encode( 1480 | | OPTIMAL_USAGE_FACTOR, 1481 | * | market, 1482 | * | isLong 1483 | | )); 1484 | | } 1485 | | 1486 | | // @dev key for base borrowing factor 1487 | | // @param market the market to check 1488 | | // @param isLong whether to get the key for the long or short side 1489 | | // @return key for base borrowing factor 1490 | | function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1491 | | return keccak256(abi.encode( 1492 | | BASE_BORROWING_FACTOR, 1493 | | market, 1494 | | isLong 1495 | | )); 1496 | | } 1497 | | 1498 | | // @dev key for above optimal usage borrowing factor 1499 | | // @param market the market to check 1500 | | // @param isLong whether to get the key for the long or short side 1501 | | // @return key for above optimal usage borrowing factor 1502 | | function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1503 | | return keccak256(abi.encode( 1504 | | ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR, 1505 | | market, 1506 | | isLong 1507 | | )); 1508 | | } 1509 | | 1510 | | // @dev key for borrowing factor 1511 | | // @param market the market to check 1512 | | // @param isLong whether to get the key for the long or short side 1513 | | // @return key for borrowing factor 1514 | * | function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1515 | * | return keccak256(abi.encode( 1516 | | BORROWING_FACTOR, 1517 | * | market, 1518 | * | isLong 1519 | | )); 1520 | | } 1521 | | 1522 | | // @dev the key for borrowing exponent 1523 | | // @param market the market for the pool 1524 | | // @param isLong whether to get the key for the long or short side 1525 | * | function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1526 | * | return keccak256(abi.encode( 1527 | | BORROWING_EXPONENT_FACTOR, 1528 | * | market, 1529 | * | isLong 1530 | | )); 1531 | | } 1532 | | 1533 | | // @dev key for cumulative borrowing factor 1534 | | // @param market the market to check 1535 | | // @param isLong whether to get the key for the long or short side 1536 | | // @return key for cumulative borrowing factor 1537 | * | function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) { 1538 | * | return keccak256(abi.encode( 1539 | | CUMULATIVE_BORROWING_FACTOR, 1540 | * | market, 1541 | * | isLong 1542 | | )); 1543 | | } 1544 | | 1545 | | // @dev key for cumulative borrowing factor updated at 1546 | | // @param market the market to check 1547 | | // @param isLong whether to get the key for the long or short side 1548 | | // @return key for cumulative borrowing factor updated at 1549 | * | function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) { 1550 | * | return keccak256(abi.encode( 1551 | | CUMULATIVE_BORROWING_FACTOR_UPDATED_AT, 1552 | * | market, 1553 | * | isLong 1554 | | )); 1555 | | } 1556 | | 1557 | | // @dev key for total borrowing amount 1558 | | // @param market the market to check 1559 | | // @param isLong whether to get the key for the long or short side 1560 | | // @return key for total borrowing amount 1561 | * | function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) { 1562 | * | return keccak256(abi.encode( 1563 | | TOTAL_BORROWING, 1564 | * | market, 1565 | * | isLong 1566 | | )); 1567 | | } 1568 | | 1569 | | // @dev key for affiliate reward amount 1570 | | // @param market the market to check 1571 | | // @param token the token to get the key for 1572 | | // @param account the account to get the key for 1573 | | // @return key for affiliate reward amount 1574 | * | function affiliateRewardKey(address market, address token) internal pure returns (bytes32) { 1575 | * | return keccak256(abi.encode( 1576 | | AFFILIATE_REWARD, 1577 | * | market, 1578 | * | token 1579 | | )); 1580 | | } 1581 | | 1582 | | function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) { 1583 | | return keccak256(abi.encode( 1584 | | MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT, 1585 | | account, 1586 | | subaccount, 1587 | | actionType 1588 | | )); 1589 | | } 1590 | | 1591 | | function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) { 1592 | | return keccak256(abi.encode( 1593 | | SUBACCOUNT_ACTION_COUNT, 1594 | | account, 1595 | | subaccount, 1596 | | actionType 1597 | | )); 1598 | | } 1599 | | 1600 | | function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) { 1601 | | return keccak256(abi.encode( 1602 | | SUBACCOUNT_AUTO_TOP_UP_AMOUNT, 1603 | | account, 1604 | | subaccount 1605 | | )); 1606 | | } 1607 | | 1608 | | // @dev key for affiliate reward amount for an account 1609 | | // @param market the market to check 1610 | | // @param token the token to get the key for 1611 | | // @param account the account to get the key for 1612 | | // @return key for affiliate reward amount 1613 | | function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) { 1614 | | return keccak256(abi.encode( 1615 | | AFFILIATE_REWARD, 1616 | | market, 1617 | | token, 1618 | | account 1619 | | )); 1620 | | } 1621 | | 1622 | | // @dev key for is market disabled 1623 | | // @param market the market to check 1624 | | // @return key for is market disabled 1625 | * | function isMarketDisabledKey(address market) internal pure returns (bytes32) { 1626 | * | return keccak256(abi.encode( 1627 | | IS_MARKET_DISABLED, 1628 | * | market 1629 | | )); 1630 | | } 1631 | | 1632 | | // @dev key for min market tokens for first deposit 1633 | | // @param market the market to check 1634 | | // @return key for min market tokens for first deposit 1635 | | function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) { 1636 | | return keccak256(abi.encode( 1637 | | MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT, 1638 | | market 1639 | | )); 1640 | | } 1641 | | 1642 | | // @dev key for price feed address 1643 | | // @param token the token to get the key for 1644 | | // @return key for price feed address 1645 | | function priceFeedKey(address token) internal pure returns (bytes32) { 1646 | | return keccak256(abi.encode( 1647 | | PRICE_FEED, 1648 | | token 1649 | | )); 1650 | | } 1651 | | 1652 | | // @dev key for data stream feed ID 1653 | | // @param token the token to get the key for 1654 | | // @return key for data stream feed ID 1655 | | function dataStreamIdKey(address token) internal pure returns (bytes32) { 1656 | | return keccak256(abi.encode( 1657 | | DATA_STREAM_ID, 1658 | | token 1659 | | )); 1660 | | } 1661 | | 1662 | | // @dev key for data stream feed multiplier 1663 | | // @param token the token to get the key for 1664 | | // @return key for data stream feed multiplier 1665 | | function dataStreamMultiplierKey(address token) internal pure returns (bytes32) { 1666 | | return keccak256(abi.encode( 1667 | | DATA_STREAM_MULTIPLIER, 1668 | | token 1669 | | )); 1670 | | } 1671 | | 1672 | | // @dev key for price feed multiplier 1673 | | // @param token the token to get the key for 1674 | | // @return key for price feed multiplier 1675 | | function priceFeedMultiplierKey(address token) internal pure returns (bytes32) { 1676 | | return keccak256(abi.encode( 1677 | | PRICE_FEED_MULTIPLIER, 1678 | | token 1679 | | )); 1680 | | } 1681 | | 1682 | | function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) { 1683 | | return keccak256(abi.encode( 1684 | | PRICE_FEED_HEARTBEAT_DURATION, 1685 | | token 1686 | | )); 1687 | | } 1688 | | 1689 | | // @dev key for stable price value 1690 | | // @param token the token to get the key for 1691 | | // @return key for stable price value 1692 | | function stablePriceKey(address token) internal pure returns (bytes32) { 1693 | | return keccak256(abi.encode( 1694 | | STABLE_PRICE, 1695 | | token 1696 | | )); 1697 | | } 1698 | | 1699 | | // @dev key for fee distributor swap token index 1700 | | // @param orderKey the swap order key 1701 | | // @return key for fee distributor swap token index 1702 | | function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) { 1703 | | return keccak256(abi.encode( 1704 | | FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX, 1705 | | orderKey 1706 | | )); 1707 | | } 1708 | | 1709 | | // @dev key for fee distributor swap fee batch key 1710 | | // @param orderKey the swap order key 1711 | | // @return key for fee distributor swap fee batch key 1712 | | function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) { 1713 | | return keccak256(abi.encode( 1714 | | FEE_DISTRIBUTOR_SWAP_FEE_BATCH, 1715 | | orderKey 1716 | | )); 1717 | | } 1718 | | 1719 | | // @dev key for glv pending shift 1720 | | // @param glv the glv for the pending shift 1721 | | function glvPendingShiftKey(address glv) internal pure returns (bytes32) { 1722 | | return keccak256(abi.encode(GLV_PENDING_SHIFT, glv)); 1723 | | } 1724 | | 1725 | | function glvPendingShiftBackrefKey(bytes32 shiftKey) internal pure returns (bytes32) { 1726 | | return keccak256(abi.encode(GLV_PENDING_SHIFT_BACKREF, shiftKey)); 1727 | | } 1728 | | 1729 | | // @dev key for max market token balance for glv 1730 | | // @param glv the glv to check the market token balance for 1731 | | // @param market the market to check balance 1732 | | function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) { 1733 | | return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market)); 1734 | | } 1735 | | 1736 | | // @dev key for is glv market disabled 1737 | | // @param glv the glv to check 1738 | | // @param market the market to check 1739 | | // @return key for is market disabled 1740 | | function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) { 1741 | | return keccak256(abi.encode( 1742 | | IS_GLV_MARKET_DISABLED, 1743 | | glv, 1744 | | market 1745 | | )); 1746 | | } 1747 | | } 1748 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/Deposit.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title Deposit 6 | | // @dev Struct for deposits 7 | * | library Deposit { 8 | | // @dev there is a limit on the number of fields a struct can have when being passed 9 | | // or returned as a memory variable which can cause "Stack too deep" errors 10 | | // use sub-structs to avoid this issue 11 | | // @param addresses address values 12 | | // @param numbers number values 13 | | // @param flags boolean values 14 | | struct Props { 15 | | Addresses addresses; 16 | | Numbers numbers; 17 | | Flags flags; 18 | | } 19 | | 20 | | // @param account the account depositing liquidity 21 | | // @param receiver the address to send the liquidity tokens to 22 | | // @param callbackContract the callback contract 23 | | // @param uiFeeReceiver the ui fee receiver 24 | | // @param market the market to deposit to 25 | | struct Addresses { 26 | | address account; 27 | | address receiver; 28 | | address callbackContract; 29 | | address uiFeeReceiver; 30 | | address market; 31 | | address initialLongToken; 32 | | address initialShortToken; 33 | | address[] longTokenSwapPath; 34 | | address[] shortTokenSwapPath; 35 | | } 36 | | 37 | | // @param initialLongTokenAmount the amount of long tokens to deposit 38 | | // @param initialShortTokenAmount the amount of short tokens to deposit 39 | | // @param minMarketTokens the minimum acceptable number of liquidity tokens 40 | | // @param updatedAtBlock the block that the deposit was last updated at 41 | | // sending funds back to the user in case the deposit gets cancelled 42 | | // @param executionFee the execution fee for keepers 43 | | // @param callbackGasLimit the gas limit for the callbackContract 44 | | struct Numbers { 45 | | uint256 initialLongTokenAmount; 46 | | uint256 initialShortTokenAmount; 47 | | uint256 minMarketTokens; 48 | | uint256 updatedAtBlock; 49 | | uint256 updatedAtTime; 50 | | uint256 executionFee; 51 | | uint256 callbackGasLimit; 52 | | } 53 | | 54 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when 55 | | struct Flags { 56 | | bool shouldUnwrapNativeToken; 57 | | } 58 | | 59 | * | function account(Props memory props) internal pure returns (address) { 60 | * | return props.addresses.account; 61 | | } 62 | | 63 | * | function setAccount(Props memory props, address value) internal pure { 64 | * | props.addresses.account = value; 65 | | } 66 | | 67 | * | function receiver(Props memory props) internal pure returns (address) { 68 | * | return props.addresses.receiver; 69 | | } 70 | | 71 | * | function setReceiver(Props memory props, address value) internal pure { 72 | * | props.addresses.receiver = value; 73 | | } 74 | | 75 | * | function callbackContract(Props memory props) internal pure returns (address) { 76 | * | return props.addresses.callbackContract; 77 | | } 78 | | 79 | * | function setCallbackContract(Props memory props, address value) internal pure { 80 | * | props.addresses.callbackContract = value; 81 | | } 82 | | 83 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) { 84 | * | return props.addresses.uiFeeReceiver; 85 | | } 86 | | 87 | * | function setUiFeeReceiver(Props memory props, address value) internal pure { 88 | * | props.addresses.uiFeeReceiver = value; 89 | | } 90 | | 91 | * | function market(Props memory props) internal pure returns (address) { 92 | * | return props.addresses.market; 93 | | } 94 | | 95 | * | function setMarket(Props memory props, address value) internal pure { 96 | * | props.addresses.market = value; 97 | | } 98 | | 99 | * | function initialLongToken(Props memory props) internal pure returns (address) { 100 | * | return props.addresses.initialLongToken; 101 | | } 102 | | 103 | * | function setInitialLongToken(Props memory props, address value) internal pure { 104 | * | props.addresses.initialLongToken = value; 105 | | } 106 | | 107 | * | function initialShortToken(Props memory props) internal pure returns (address) { 108 | * | return props.addresses.initialShortToken; 109 | | } 110 | | 111 | * | function setInitialShortToken(Props memory props, address value) internal pure { 112 | * | props.addresses.initialShortToken = value; 113 | | } 114 | | 115 | * | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 116 | * | return props.addresses.longTokenSwapPath; 117 | | } 118 | | 119 | * | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure { 120 | * | props.addresses.longTokenSwapPath = value; 121 | | } 122 | | 123 | * | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 124 | * | return props.addresses.shortTokenSwapPath; 125 | | } 126 | | 127 | * | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure { 128 | * | props.addresses.shortTokenSwapPath = value; 129 | | } 130 | | 131 | * | function initialLongTokenAmount(Props memory props) internal pure returns (uint256) { 132 | * | return props.numbers.initialLongTokenAmount; 133 | | } 134 | | 135 | * | function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure { 136 | * | props.numbers.initialLongTokenAmount = value; 137 | | } 138 | | 139 | * | function initialShortTokenAmount(Props memory props) internal pure returns (uint256) { 140 | * | return props.numbers.initialShortTokenAmount; 141 | | } 142 | | 143 | * | function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure { 144 | * | props.numbers.initialShortTokenAmount = value; 145 | | } 146 | | 147 | * | function minMarketTokens(Props memory props) internal pure returns (uint256) { 148 | * | return props.numbers.minMarketTokens; 149 | | } 150 | | 151 | * | function setMinMarketTokens(Props memory props, uint256 value) internal pure { 152 | * | props.numbers.minMarketTokens = value; 153 | | } 154 | | 155 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) { 156 | * | return props.numbers.updatedAtBlock; 157 | | } 158 | | 159 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure { 160 | * | props.numbers.updatedAtBlock = value; 161 | | } 162 | | 163 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) { 164 | * | return props.numbers.updatedAtTime; 165 | | } 166 | | 167 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure { 168 | * | props.numbers.updatedAtTime = value; 169 | | } 170 | | 171 | * | function executionFee(Props memory props) internal pure returns (uint256) { 172 | * | return props.numbers.executionFee; 173 | | } 174 | | 175 | * | function setExecutionFee(Props memory props, uint256 value) internal pure { 176 | * | props.numbers.executionFee = value; 177 | | } 178 | | 179 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) { 180 | * | return props.numbers.callbackGasLimit; 181 | | } 182 | | 183 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure { 184 | * | props.numbers.callbackGasLimit = value; 185 | | } 186 | | 187 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) { 188 | * | return props.flags.shouldUnwrapNativeToken; 189 | | } 190 | | 191 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure { 192 | * | props.flags.shouldUnwrapNativeToken = value; 193 | | } 194 | | } 195 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./Deposit.sol"; 10 | | import "./DepositUtils.sol"; 11 | | import "../pricing/ISwapPricingUtils.sol"; 12 | | 13 | * | library DepositEventUtils { 14 | | using Deposit for Deposit.Props; 15 | | 16 | | using EventUtils for EventUtils.AddressItems; 17 | | using EventUtils for EventUtils.UintItems; 18 | | using EventUtils for EventUtils.IntItems; 19 | | using EventUtils for EventUtils.BoolItems; 20 | | using EventUtils for EventUtils.Bytes32Items; 21 | | using EventUtils for EventUtils.BytesItems; 22 | | using EventUtils for EventUtils.StringItems; 23 | | 24 | * | function emitDepositCreated( 25 | | EventEmitter eventEmitter, 26 | | bytes32 key, 27 | | Deposit.Props memory deposit, 28 | | DepositUtils.DepositType depositType 29 | * | ) internal { 30 | * | EventUtils.EventLogData memory eventData; 31 | | 32 | * | eventData.addressItems.initItems(6); 33 | * | eventData.addressItems.setItem(0, "account", deposit.account()); 34 | * | eventData.addressItems.setItem(1, "receiver", deposit.receiver()); 35 | * | eventData.addressItems.setItem(2, "callbackContract", deposit.callbackContract()); 36 | * | eventData.addressItems.setItem(3, "market", deposit.market()); 37 | * | eventData.addressItems.setItem(4, "initialLongToken", deposit.initialLongToken()); 38 | * | eventData.addressItems.setItem(5, "initialShortToken", deposit.initialShortToken()); 39 | | 40 | * | eventData.addressItems.initArrayItems(2); 41 | * | eventData.addressItems.setItem(0, "longTokenSwapPath", deposit.longTokenSwapPath()); 42 | * | eventData.addressItems.setItem(1, "shortTokenSwapPath", deposit.shortTokenSwapPath()); 43 | | 44 | * | eventData.uintItems.initItems(8); 45 | * | eventData.uintItems.setItem(0, "initialLongTokenAmount", deposit.initialLongTokenAmount()); 46 | * | eventData.uintItems.setItem(1, "initialShortTokenAmount", deposit.initialShortTokenAmount()); 47 | * | eventData.uintItems.setItem(2, "minMarketTokens", deposit.minMarketTokens()); 48 | * | eventData.uintItems.setItem(3, "updatedAtBlock", deposit.updatedAtBlock()); 49 | * | eventData.uintItems.setItem(4, "updatedAtTime", deposit.updatedAtTime()); 50 | * | eventData.uintItems.setItem(5, "executionFee", deposit.executionFee()); 51 | * | eventData.uintItems.setItem(6, "callbackGasLimit", deposit.callbackGasLimit()); 52 | * | eventData.uintItems.setItem(7, "depositType", uint256(depositType)); 53 | | 54 | * | eventData.boolItems.initItems(1); 55 | * | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", deposit.shouldUnwrapNativeToken()); 56 | | 57 | * | eventData.bytes32Items.initItems(1); 58 | * | eventData.bytes32Items.setItem(0, "key", key); 59 | | 60 | * | eventEmitter.emitEventLog2( 61 | | "DepositCreated", 62 | * | key, 63 | * | Cast.toBytes32(deposit.account()), 64 | * | eventData 65 | | ); 66 | | } 67 | | 68 | * | function emitDepositExecuted( 69 | | EventEmitter eventEmitter, 70 | | bytes32 key, 71 | | address account, 72 | | uint256 longTokenAmount, 73 | | uint256 shortTokenAmount, 74 | | uint256 receivedMarketTokens, 75 | | ISwapPricingUtils.SwapPricingType swapPricingType 76 | * | ) internal { 77 | * | EventUtils.EventLogData memory eventData; 78 | | 79 | * | eventData.bytes32Items.initItems(1); 80 | * | eventData.bytes32Items.setItem(0, "key", key); 81 | | 82 | * | eventData.addressItems.initItems(1); 83 | * | eventData.addressItems.setItem(0, "account", account); 84 | | 85 | * | eventData.uintItems.initItems(4); 86 | * | eventData.uintItems.setItem(0, "longTokenAmount", longTokenAmount); 87 | * | eventData.uintItems.setItem(1, "shortTokenAmount", shortTokenAmount); 88 | * | eventData.uintItems.setItem(2, "receivedMarketTokens", receivedMarketTokens); 89 | * | eventData.uintItems.setItem(3, "swapPricingType", uint256(swapPricingType)); 90 | | 91 | * | eventEmitter.emitEventLog2( 92 | | "DepositExecuted", 93 | * | key, 94 | * | Cast.toBytes32(account), 95 | * | eventData 96 | | ); 97 | | } 98 | | 99 | * | function emitDepositCancelled( 100 | | EventEmitter eventEmitter, 101 | | bytes32 key, 102 | | address account, 103 | | string memory reason, 104 | | bytes memory reasonBytes 105 | * | ) internal { 106 | * | EventUtils.EventLogData memory eventData; 107 | | 108 | * | eventData.bytes32Items.initItems(1); 109 | * | eventData.bytes32Items.setItem(0, "key", key); 110 | | 111 | * | eventData.addressItems.initItems(1); 112 | * | eventData.addressItems.setItem(0, "account", account); 113 | | 114 | * | eventData.stringItems.initItems(1); 115 | * | eventData.stringItems.setItem(0, "reason", reason); 116 | | 117 | * | eventData.bytesItems.initItems(1); 118 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 119 | | 120 | * | eventEmitter.emitEventLog2( 121 | | "DepositCancelled", 122 | * | key, 123 | * | Cast.toBytes32(account), 124 | * | eventData 125 | | ); 126 | | } 127 | | } 128 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Deposit.sol"; 9 | | 10 | | /** 11 | | * @title DepositStoreUtils 12 | | * @dev Library for deposit storage functions 13 | | */ 14 | * | library DepositStoreUtils { 15 | | using Deposit for Deposit.Props; 16 | | 17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER")); 19 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT")); 20 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER")); 21 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET")); 22 | * | bytes32 internal constant INITIAL_LONG_TOKEN = keccak256(abi.encode("INITIAL_LONG_TOKEN")); 23 | * | bytes32 internal constant INITIAL_SHORT_TOKEN = keccak256(abi.encode("INITIAL_SHORT_TOKEN")); 24 | * | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH")); 25 | * | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH")); 26 | | 27 | * | bytes32 internal constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_LONG_TOKEN_AMOUNT")); 28 | * | bytes32 internal constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_SHORT_TOKEN_AMOUNT")); 29 | * | bytes32 internal constant MIN_MARKET_TOKENS = keccak256(abi.encode("MIN_MARKET_TOKENS")); 30 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK")); 31 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME")); 32 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE")); 33 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT")); 34 | | 35 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN")); 36 | | 37 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Deposit.Props memory) { 38 | * | Deposit.Props memory deposit; 39 | * | if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) { 40 | | return deposit; 41 | | } 42 | | 43 | * | deposit.setAccount(dataStore.getAddress( 44 | * | keccak256(abi.encode(key, ACCOUNT)) 45 | | )); 46 | | 47 | * | deposit.setReceiver(dataStore.getAddress( 48 | * | keccak256(abi.encode(key, RECEIVER)) 49 | | )); 50 | | 51 | * | deposit.setCallbackContract(dataStore.getAddress( 52 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 53 | | )); 54 | | 55 | * | deposit.setUiFeeReceiver(dataStore.getAddress( 56 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 57 | | )); 58 | | 59 | * | deposit.setMarket(dataStore.getAddress( 60 | * | keccak256(abi.encode(key, MARKET)) 61 | | )); 62 | | 63 | * | deposit.setInitialLongToken(dataStore.getAddress( 64 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)) 65 | | )); 66 | | 67 | * | deposit.setInitialShortToken(dataStore.getAddress( 68 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)) 69 | | )); 70 | | 71 | * | deposit.setLongTokenSwapPath(dataStore.getAddressArray( 72 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 73 | | )); 74 | | 75 | * | deposit.setShortTokenSwapPath(dataStore.getAddressArray( 76 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 77 | | )); 78 | | 79 | * | deposit.setInitialLongTokenAmount(dataStore.getUint( 80 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)) 81 | | )); 82 | | 83 | * | deposit.setInitialShortTokenAmount(dataStore.getUint( 84 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)) 85 | | )); 86 | | 87 | * | deposit.setMinMarketTokens(dataStore.getUint( 88 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS)) 89 | | )); 90 | | 91 | * | deposit.setUpdatedAtBlock(dataStore.getUint( 92 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 93 | | )); 94 | | 95 | * | deposit.setUpdatedAtTime(dataStore.getUint( 96 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 97 | | )); 98 | | 99 | * | deposit.setExecutionFee(dataStore.getUint( 100 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 101 | | )); 102 | | 103 | * | deposit.setCallbackGasLimit(dataStore.getUint( 104 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 105 | | )); 106 | | 107 | * | deposit.setShouldUnwrapNativeToken(dataStore.getBool( 108 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 109 | | )); 110 | | 111 | * | return deposit; 112 | | } 113 | | 114 | * | function set(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) internal { 115 | * | dataStore.addBytes32( 116 | | Keys.DEPOSIT_LIST, 117 | * | key 118 | | ); 119 | | 120 | * | dataStore.addBytes32( 121 | * | Keys.accountDepositListKey(deposit.account()), 122 | * | key 123 | | ); 124 | | 125 | * | dataStore.setAddress( 126 | * | keccak256(abi.encode(key, ACCOUNT)), 127 | * | deposit.account() 128 | | ); 129 | | 130 | * | dataStore.setAddress( 131 | * | keccak256(abi.encode(key, RECEIVER)), 132 | * | deposit.receiver() 133 | | ); 134 | | 135 | * | dataStore.setAddress( 136 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)), 137 | * | deposit.callbackContract() 138 | | ); 139 | | 140 | * | dataStore.setAddress( 141 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)), 142 | * | deposit.uiFeeReceiver() 143 | | ); 144 | | 145 | * | dataStore.setAddress( 146 | * | keccak256(abi.encode(key, MARKET)), 147 | * | deposit.market() 148 | | ); 149 | | 150 | * | dataStore.setAddress( 151 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)), 152 | * | deposit.initialLongToken() 153 | | ); 154 | | 155 | * | dataStore.setAddress( 156 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)), 157 | * | deposit.initialShortToken() 158 | | ); 159 | | 160 | * | dataStore.setAddressArray( 161 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)), 162 | * | deposit.longTokenSwapPath() 163 | | ); 164 | | 165 | * | dataStore.setAddressArray( 166 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)), 167 | * | deposit.shortTokenSwapPath() 168 | | ); 169 | | 170 | * | dataStore.setUint( 171 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)), 172 | * | deposit.initialLongTokenAmount() 173 | | ); 174 | | 175 | * | dataStore.setUint( 176 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)), 177 | * | deposit.initialShortTokenAmount() 178 | | ); 179 | | 180 | * | dataStore.setUint( 181 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS)), 182 | * | deposit.minMarketTokens() 183 | | ); 184 | | 185 | * | dataStore.setUint( 186 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)), 187 | * | deposit.updatedAtBlock() 188 | | ); 189 | | 190 | * | dataStore.setUint( 191 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)), 192 | * | deposit.updatedAtTime() 193 | | ); 194 | | 195 | * | dataStore.setUint( 196 | * | keccak256(abi.encode(key, EXECUTION_FEE)), 197 | * | deposit.executionFee() 198 | | ); 199 | | 200 | * | dataStore.setUint( 201 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)), 202 | * | deposit.callbackGasLimit() 203 | | ); 204 | | 205 | * | dataStore.setBool( 206 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)), 207 | * | deposit.shouldUnwrapNativeToken() 208 | | ); 209 | | } 210 | | 211 | * | function remove(DataStore dataStore, bytes32 key, address account) internal { 212 | * | if (!dataStore.containsBytes32(Keys.DEPOSIT_LIST, key)) { 213 | | revert Errors.DepositNotFound(key); 214 | | } 215 | | 216 | * | dataStore.removeBytes32( 217 | | Keys.DEPOSIT_LIST, 218 | * | key 219 | | ); 220 | | 221 | * | dataStore.removeBytes32( 222 | * | Keys.accountDepositListKey(account), 223 | * | key 224 | | ); 225 | | 226 | * | dataStore.removeAddress( 227 | * | keccak256(abi.encode(key, ACCOUNT)) 228 | | ); 229 | | 230 | * | dataStore.removeAddress( 231 | * | keccak256(abi.encode(key, RECEIVER)) 232 | | ); 233 | | 234 | * | dataStore.removeAddress( 235 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 236 | | ); 237 | | 238 | * | dataStore.removeAddress( 239 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 240 | | ); 241 | | 242 | * | dataStore.removeAddress( 243 | * | keccak256(abi.encode(key, MARKET)) 244 | | ); 245 | | 246 | * | dataStore.removeAddress( 247 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)) 248 | | ); 249 | | 250 | * | dataStore.removeAddress( 251 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)) 252 | | ); 253 | | 254 | * | dataStore.removeAddressArray( 255 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 256 | | ); 257 | | 258 | * | dataStore.removeAddressArray( 259 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 260 | | ); 261 | | 262 | * | dataStore.removeUint( 263 | * | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)) 264 | | ); 265 | | 266 | * | dataStore.removeUint( 267 | * | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)) 268 | | ); 269 | | 270 | * | dataStore.removeUint( 271 | * | keccak256(abi.encode(key, MIN_MARKET_TOKENS)) 272 | | ); 273 | | 274 | * | dataStore.removeUint( 275 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 276 | | ); 277 | | 278 | * | dataStore.removeUint( 279 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 280 | | ); 281 | | 282 | * | dataStore.removeUint( 283 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 284 | | ); 285 | | 286 | * | dataStore.removeUint( 287 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 288 | | ); 289 | | 290 | * | dataStore.removeBool( 291 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 292 | | ); 293 | | } 294 | | 295 | | function getDepositCount(DataStore dataStore) internal view returns (uint256) { 296 | | return dataStore.getBytes32Count(Keys.DEPOSIT_LIST); 297 | | } 298 | | 299 | | function getDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 300 | | return dataStore.getBytes32ValuesAt(Keys.DEPOSIT_LIST, start, end); 301 | | } 302 | | 303 | | function getAccountDepositCount(DataStore dataStore, address account) internal view returns (uint256) { 304 | | return dataStore.getBytes32Count(Keys.accountDepositListKey(account)); 305 | | } 306 | | 307 | | function getAccountDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 308 | | return dataStore.getBytes32ValuesAt(Keys.accountDepositListKey(account), start, end); 309 | | } 310 | | } 311 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | 8 | | import "./DepositVault.sol"; 9 | | import "./DepositStoreUtils.sol"; 10 | | import "./DepositEventUtils.sol"; 11 | | 12 | | import "../nonce/NonceUtils.sol"; 13 | | 14 | | import "../gas/GasUtils.sol"; 15 | | import "../callback/CallbackUtils.sol"; 16 | | import "../utils/AccountUtils.sol"; 17 | | 18 | | // @title DepositUtils 19 | | // @dev Library for deposit functions, to help with the depositing of liquidity 20 | | // into a market in return for market tokens 21 | * | library DepositUtils { 22 | | using SafeCast for uint256; 23 | | using SafeCast for int256; 24 | | 25 | | using Price for Price.Props; 26 | | using Deposit for Deposit.Props; 27 | | 28 | | enum DepositType { 29 | | Normal, 30 | | Shift, 31 | | Glv 32 | | } 33 | | 34 | | // @dev CreateDepositParams struct used in createDeposit to avoid stack 35 | | // too deep errors 36 | | // 37 | | // @param receiver the address to send the market tokens to 38 | | // @param callbackContract the callback contract 39 | | // @param uiFeeReceiver the ui fee receiver 40 | | // @param market the market to deposit into 41 | | // @param minMarketTokens the minimum acceptable number of liquidity tokens 42 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when 43 | | // sending funds back to the user in case the deposit gets cancelled 44 | | // @param executionFee the execution fee for keepers 45 | | // @param callbackGasLimit the gas limit for the callbackContract 46 | | struct CreateDepositParams { 47 | | address receiver; 48 | | address callbackContract; 49 | | address uiFeeReceiver; 50 | | address market; 51 | | address initialLongToken; 52 | | address initialShortToken; 53 | | address[] longTokenSwapPath; 54 | | address[] shortTokenSwapPath; 55 | | uint256 minMarketTokens; 56 | | bool shouldUnwrapNativeToken; 57 | | uint256 executionFee; 58 | | uint256 callbackGasLimit; 59 | | } 60 | | 61 | | // @dev creates a deposit 62 | | // 63 | | // @param dataStore DataStore 64 | | // @param eventEmitter EventEmitter 65 | | // @param depositVault DepositVault 66 | | // @param account the depositing account 67 | | // @param params CreateDepositParams 68 | * | function createDeposit( 69 | | DataStore dataStore, 70 | | EventEmitter eventEmitter, 71 | | DepositVault depositVault, 72 | | address account, 73 | | CreateDepositParams memory params 74 | * | ) internal returns (bytes32) { 75 | * | AccountUtils.validateAccount(account); 76 | | 77 | * | Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, params.market); 78 | * | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath); 79 | * | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath); 80 | | 81 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would 82 | | // be non-zero, the initialShortTokenAmount would be zero 83 | * | uint256 initialLongTokenAmount = depositVault.recordTransferIn(params.initialLongToken); 84 | * | uint256 initialShortTokenAmount = depositVault.recordTransferIn(params.initialShortToken); 85 | | 86 | * | address wnt = TokenUtils.wnt(dataStore); 87 | | 88 | * | if (params.initialLongToken == wnt) { 89 | * | initialLongTokenAmount -= params.executionFee; 90 | * | } else if (params.initialShortToken == wnt) { 91 | | initialShortTokenAmount -= params.executionFee; 92 | * | } else { 93 | * | uint256 wntAmount = depositVault.recordTransferIn(wnt); 94 | * | if (wntAmount < params.executionFee) { 95 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee); 96 | | } 97 | | 98 | * | params.executionFee = wntAmount; 99 | | } 100 | | 101 | * | if (initialLongTokenAmount == 0 && initialShortTokenAmount == 0) { 102 | | revert Errors.EmptyDepositAmounts(); 103 | | } 104 | | 105 | * | AccountUtils.validateReceiver(params.receiver); 106 | | 107 | * | Deposit.Props memory deposit = Deposit.Props( 108 | * | Deposit.Addresses( 109 | * | account, 110 | * | params.receiver, 111 | * | params.callbackContract, 112 | * | params.uiFeeReceiver, 113 | * | market.marketToken, 114 | * | params.initialLongToken, 115 | * | params.initialShortToken, 116 | * | params.longTokenSwapPath, 117 | * | params.shortTokenSwapPath 118 | | ), 119 | * | Deposit.Numbers( 120 | * | initialLongTokenAmount, 121 | * | initialShortTokenAmount, 122 | * | params.minMarketTokens, 123 | * | Chain.currentBlockNumber(), 124 | * | Chain.currentTimestamp(), 125 | * | params.executionFee, 126 | * | params.callbackGasLimit 127 | | ), 128 | * | Deposit.Flags( 129 | * | params.shouldUnwrapNativeToken 130 | | ) 131 | | ); 132 | | 133 | * | CallbackUtils.validateCallbackGasLimit(dataStore, deposit.callbackGasLimit()); 134 | | 135 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit); 136 | * | uint256 oraclePriceCount = GasUtils.estimateDepositOraclePriceCount( 137 | * | deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length 138 | | ); 139 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount); 140 | | 141 | * | bytes32 key = NonceUtils.getNextKey(dataStore); 142 | | 143 | * | DepositStoreUtils.set(dataStore, key, deposit); 144 | | 145 | * | DepositEventUtils.emitDepositCreated(eventEmitter, key, deposit, DepositType.Normal); 146 | | 147 | * | return key; 148 | | } 149 | | 150 | | // @dev cancels a deposit, funds are sent back to the user 151 | | // 152 | | // @param dataStore DataStore 153 | | // @param eventEmitter EventEmitter 154 | | // @param depositVault DepositVault 155 | | // @param key the key of the deposit to cancel 156 | | // @param keeper the address of the keeper 157 | | // @param startingGas the starting gas amount 158 | * | function cancelDeposit( 159 | | DataStore dataStore, 160 | | EventEmitter eventEmitter, 161 | | DepositVault depositVault, 162 | | bytes32 key, 163 | | address keeper, 164 | | uint256 startingGas, 165 | | string memory reason, 166 | | bytes memory reasonBytes 167 | * | ) internal { 168 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 169 | * | startingGas -= gasleft() / 63; 170 | | 171 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key); 172 | * | if (deposit.account() == address(0)) { 173 | | revert Errors.EmptyDeposit(); 174 | | } 175 | | 176 | * | if ( 177 | * | deposit.initialLongTokenAmount() == 0 && 178 | | deposit.initialShortTokenAmount() == 0 179 | | ) { 180 | | revert Errors.EmptyDepositAmounts(); 181 | | } 182 | | 183 | * | DepositStoreUtils.remove(dataStore, key, deposit.account()); 184 | | 185 | * | if (deposit.initialLongTokenAmount() > 0) { 186 | * | depositVault.transferOut( 187 | * | deposit.initialLongToken(), 188 | * | deposit.account(), 189 | * | deposit.initialLongTokenAmount(), 190 | * | deposit.shouldUnwrapNativeToken() 191 | | ); 192 | | } 193 | | 194 | * | if (deposit.initialShortTokenAmount() > 0) { 195 | * | depositVault.transferOut( 196 | * | deposit.initialShortToken(), 197 | * | deposit.account(), 198 | * | deposit.initialShortTokenAmount(), 199 | * | deposit.shouldUnwrapNativeToken() 200 | | ); 201 | | } 202 | | 203 | * | DepositEventUtils.emitDepositCancelled( 204 | * | eventEmitter, 205 | * | key, 206 | * | deposit.account(), 207 | * | reason, 208 | * | reasonBytes 209 | | ); 210 | | 211 | * | EventUtils.EventLogData memory eventData; 212 | * | CallbackUtils.afterDepositCancellation(key, deposit, eventData); 213 | | 214 | * | GasUtils.payExecutionFee( 215 | * | dataStore, 216 | * | eventEmitter, 217 | * | depositVault, 218 | * | key, 219 | * | deposit.callbackContract(), 220 | * | deposit.executionFee(), 221 | * | startingGas, 222 | * | GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length), 223 | * | keeper, 224 | * | deposit.receiver() 225 | | ); 226 | | } 227 | | } 228 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/DepositVault.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../bank/StrictBank.sol"; 6 | | 7 | | // @title DepositVault 8 | | // @dev Vault for deposits 9 | * | contract DepositVault is StrictBank { 10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {} 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/deposit/ExecuteDepositUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../adl/AdlUtils.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | 10 | | import "./DepositVault.sol"; 11 | | import "./DepositStoreUtils.sol"; 12 | | import "./DepositEventUtils.sol"; 13 | | 14 | | import "../pricing/SwapPricingUtils.sol"; 15 | | import "../oracle/Oracle.sol"; 16 | | import "../oracle/OracleUtils.sol"; 17 | | 18 | | import "../gas/GasUtils.sol"; 19 | | import "../callback/CallbackUtils.sol"; 20 | | 21 | | import "../utils/Array.sol"; 22 | | import "../error/ErrorUtils.sol"; 23 | | 24 | | // @title DepositUtils 25 | | // @dev Library for deposit functions, to help with the depositing of liquidity 26 | | // into a market in return for market tokens 27 | * | library ExecuteDepositUtils { 28 | | using SafeCast for uint256; 29 | | using SafeCast for int256; 30 | | using Array for uint256[]; 31 | | 32 | | using Price for Price.Props; 33 | | using Deposit for Deposit.Props; 34 | | 35 | | using EventUtils for EventUtils.AddressItems; 36 | | using EventUtils for EventUtils.UintItems; 37 | | using EventUtils for EventUtils.IntItems; 38 | | using EventUtils for EventUtils.BoolItems; 39 | | using EventUtils for EventUtils.Bytes32Items; 40 | | using EventUtils for EventUtils.BytesItems; 41 | | using EventUtils for EventUtils.StringItems; 42 | | 43 | | // @dev ExecuteDepositParams struct used in executeDeposit to avoid stack 44 | | // too deep errors 45 | | struct ExecuteDepositParams { 46 | | DataStore dataStore; 47 | | EventEmitter eventEmitter; 48 | | DepositVault depositVault; 49 | | Oracle oracle; 50 | | bytes32 key; 51 | | address keeper; 52 | | uint256 startingGas; 53 | | ISwapPricingUtils.SwapPricingType swapPricingType; 54 | | bool includeVirtualInventoryImpact; 55 | | } 56 | | 57 | | // @dev _ExecuteDepositParams struct used in executeDeposit to avoid stack 58 | | // too deep errors 59 | | // 60 | | // @param market the market to deposit into 61 | | // @param account the depositing account 62 | | // @param receiver the account to send the market tokens to 63 | | // @param uiFeeReceiver the ui fee receiver account 64 | | // @param tokenIn the token to deposit, either the market.longToken or 65 | | // market.shortToken 66 | | // @param tokenOut the other token, if tokenIn is market.longToken then 67 | | // tokenOut is market.shortToken and vice versa 68 | | // @param tokenInPrice price of tokenIn 69 | | // @param tokenOutPrice price of tokenOut 70 | | // @param amount amount of tokenIn 71 | | // @param priceImpactUsd price impact in USD 72 | | struct _ExecuteDepositParams { 73 | | Market.Props market; 74 | | address account; 75 | | address receiver; 76 | | address uiFeeReceiver; 77 | | address tokenIn; 78 | | address tokenOut; 79 | | Price.Props tokenInPrice; 80 | | Price.Props tokenOutPrice; 81 | | uint256 amount; 82 | | int256 priceImpactUsd; 83 | | } 84 | | 85 | | struct ExecuteDepositCache { 86 | | uint256 requestExpirationTime; 87 | | uint256 maxOracleTimestamp; 88 | | Market.Props market; 89 | | MarketUtils.MarketPrices prices; 90 | | uint256 longTokenAmount; 91 | | uint256 shortTokenAmount; 92 | | uint256 longTokenUsd; 93 | | uint256 shortTokenUsd; 94 | | uint256 receivedMarketTokens; 95 | | int256 priceImpactUsd; 96 | | uint256 marketTokensSupply; 97 | | EventUtils.EventLogData callbackEventData; 98 | | } 99 | | 100 | | address internal constant RECEIVER_FOR_FIRST_DEPOSIT = address(1); 101 | | 102 | | // @dev executes a deposit 103 | | // @param params ExecuteDepositParams 104 | * | function executeDeposit(ExecuteDepositParams memory params, Deposit.Props memory deposit) internal returns (uint256 receivedMarketTokens) { 105 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 106 | * | params.startingGas -= gasleft() / 63; 107 | | 108 | * | DepositStoreUtils.remove(params.dataStore, params.key, deposit.account()); 109 | | 110 | | 111 | * | if (deposit.account() == address(0)) { 112 | | revert Errors.EmptyDeposit(); 113 | | } 114 | | 115 | * | if (params.oracle.minTimestamp() < deposit.updatedAtTime()) { 116 | * | revert Errors.OracleTimestampsAreSmallerThanRequired( 117 | * | params.oracle.minTimestamp(), 118 | * | deposit.updatedAtTime() 119 | | ); 120 | | } 121 | | 122 | * | ExecuteDepositCache memory cache; 123 | * | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 124 | * | cache.maxOracleTimestamp = params.oracle.maxTimestamp(); 125 | | 126 | * | if (cache.maxOracleTimestamp > deposit.updatedAtTime() + cache.requestExpirationTime) { 127 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 128 | * | cache.maxOracleTimestamp, 129 | * | deposit.updatedAtTime(), 130 | * | cache.requestExpirationTime 131 | | ); 132 | | } 133 | | 134 | * | cache.market = MarketUtils.getEnabledMarket(params.dataStore, deposit.market()); 135 | | 136 | * | _validateFirstDeposit(params, deposit, cache.market); 137 | | 138 | * | cache.prices = MarketUtils.getMarketPrices(params.oracle, cache.market); 139 | | 140 | * | MarketUtils.distributePositionImpactPool( 141 | * | params.dataStore, 142 | * | params.eventEmitter, 143 | * | cache.market.marketToken 144 | | ); 145 | | 146 | * | PositionUtils.updateFundingAndBorrowingState( 147 | * | params.dataStore, 148 | * | params.eventEmitter, 149 | * | cache.market, 150 | * | cache.prices 151 | | ); 152 | | 153 | | // deposits should improve the pool state but it should be checked if 154 | | // the max pnl factor for deposits is exceeded as this would lead to the 155 | | // price of the market token decreasing below a target minimum percentage 156 | | // due to pnl 157 | | // note that this is just a validation for deposits, there is no actual 158 | | // minimum price for a market token 159 | * | MarketUtils.validateMaxPnl( 160 | * | params.dataStore, 161 | * | cache.market, 162 | * | cache.prices, 163 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 164 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS 165 | | ); 166 | | 167 | * | cache.longTokenAmount = swap( 168 | * | params, 169 | * | deposit.longTokenSwapPath(), 170 | * | deposit.initialLongToken(), 171 | * | deposit.initialLongTokenAmount(), 172 | * | cache.market.marketToken, 173 | * | cache.market.longToken, 174 | * | deposit.uiFeeReceiver() 175 | | ); 176 | | 177 | * | cache.shortTokenAmount = swap( 178 | * | params, 179 | * | deposit.shortTokenSwapPath(), 180 | * | deposit.initialShortToken(), 181 | * | deposit.initialShortTokenAmount(), 182 | * | cache.market.marketToken, 183 | * | cache.market.shortToken, 184 | * | deposit.uiFeeReceiver() 185 | | ); 186 | | 187 | * | if (cache.longTokenAmount == 0 && cache.shortTokenAmount == 0) { 188 | | revert Errors.EmptyDepositAmountsAfterSwap(); 189 | | } 190 | | 191 | * | cache.longTokenUsd = cache.longTokenAmount * cache.prices.longTokenPrice.midPrice(); 192 | * | cache.shortTokenUsd = cache.shortTokenAmount * cache.prices.shortTokenPrice.midPrice(); 193 | | 194 | * | cache.priceImpactUsd = SwapPricingUtils.getPriceImpactUsd( 195 | * | SwapPricingUtils.GetPriceImpactUsdParams( 196 | * | params.dataStore, 197 | * | cache.market, 198 | * | cache.market.longToken, 199 | * | cache.market.shortToken, 200 | * | cache.prices.longTokenPrice.midPrice(), 201 | * | cache.prices.shortTokenPrice.midPrice(), 202 | * | cache.longTokenUsd.toInt256(), 203 | * | cache.shortTokenUsd.toInt256(), 204 | * | params.includeVirtualInventoryImpact 205 | | ) 206 | | ); 207 | | 208 | * | if (cache.longTokenAmount > 0) { 209 | * | _ExecuteDepositParams memory _params = _ExecuteDepositParams( 210 | * | cache.market, 211 | * | deposit.account(), 212 | * | deposit.receiver(), 213 | * | deposit.uiFeeReceiver(), 214 | * | cache.market.longToken, 215 | * | cache.market.shortToken, 216 | * | cache.prices.longTokenPrice, 217 | * | cache.prices.shortTokenPrice, 218 | * | cache.longTokenAmount, 219 | * | Precision.mulDiv(cache.priceImpactUsd, cache.longTokenUsd, cache.longTokenUsd + cache.shortTokenUsd) 220 | | ); 221 | | 222 | * | cache.receivedMarketTokens += _executeDeposit(params, _params); 223 | | } 224 | | 225 | * | if (cache.shortTokenAmount > 0) { 226 | * | _ExecuteDepositParams memory _params = _ExecuteDepositParams( 227 | * | cache.market, 228 | * | deposit.account(), 229 | * | deposit.receiver(), 230 | * | deposit.uiFeeReceiver(), 231 | * | cache.market.shortToken, 232 | * | cache.market.longToken, 233 | * | cache.prices.shortTokenPrice, 234 | * | cache.prices.longTokenPrice, 235 | * | cache.shortTokenAmount, 236 | * | Precision.mulDiv(cache.priceImpactUsd, cache.shortTokenUsd, cache.longTokenUsd + cache.shortTokenUsd) 237 | | ); 238 | | 239 | * | cache.receivedMarketTokens += _executeDeposit(params, _params); 240 | | } 241 | | 242 | * | if (cache.receivedMarketTokens < deposit.minMarketTokens()) { 243 | | revert Errors.MinMarketTokens(cache.receivedMarketTokens, deposit.minMarketTokens()); 244 | | } 245 | | 246 | | // validate that internal state changes are correct before calling 247 | | // internal callbacks 248 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, cache.market); 249 | | 250 | * | DepositEventUtils.emitDepositExecuted( 251 | * | params.eventEmitter, 252 | * | params.key, 253 | * | deposit.account(), 254 | * | cache.longTokenAmount, 255 | * | cache.shortTokenAmount, 256 | * | cache.receivedMarketTokens, 257 | * | params.swapPricingType 258 | | ); 259 | | 260 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 261 | * | params.dataStore, 262 | * | cache.market, 263 | * | cache.prices.indexTokenPrice, 264 | * | cache.prices.longTokenPrice, 265 | * | cache.prices.shortTokenPrice, 266 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 267 | * | true 268 | | ); 269 | | 270 | * | cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(cache.market.marketToken))); 271 | | 272 | * | MarketEventUtils.emitMarketPoolValueUpdated( 273 | * | params.eventEmitter, 274 | * | keccak256(abi.encode("DEPOSIT")), 275 | * | params.key, 276 | * | cache.market.marketToken, 277 | * | poolValueInfo, 278 | * | cache.marketTokensSupply 279 | | ); 280 | | 281 | * | cache.callbackEventData.uintItems.initItems(1); 282 | * | cache.callbackEventData.uintItems.setItem(0, "receivedMarketTokens", cache.receivedMarketTokens); 283 | * | CallbackUtils.afterDepositExecution(params.key, deposit, cache.callbackEventData); 284 | | 285 | * | GasUtils.payExecutionFee( 286 | * | params.dataStore, 287 | * | params.eventEmitter, 288 | * | params.depositVault, 289 | * | params.key, 290 | * | deposit.callbackContract(), 291 | * | deposit.executionFee(), 292 | * | params.startingGas, 293 | * | GasUtils.estimateDepositOraclePriceCount(deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length), 294 | * | params.keeper, 295 | * | deposit.receiver() 296 | | ); 297 | | 298 | * | return cache.receivedMarketTokens; 299 | | } 300 | | 301 | | // @dev executes a deposit 302 | | // @param params ExecuteDepositParams 303 | | // @param _params _ExecuteDepositParams 304 | * | function _executeDeposit(ExecuteDepositParams memory params, _ExecuteDepositParams memory _params) internal returns (uint256) { 305 | | // for markets where longToken == shortToken, the price impact factor should be set to zero 306 | | // in which case, the priceImpactUsd would always equal zero 307 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees( 308 | * | params.dataStore, 309 | * | _params.market.marketToken, 310 | * | _params.amount, 311 | * | _params.priceImpactUsd > 0, // forPositiveImpact 312 | * | _params.uiFeeReceiver, 313 | * | params.swapPricingType 314 | | ); 315 | | 316 | * | FeeUtils.incrementClaimableFeeAmount( 317 | * | params.dataStore, 318 | * | params.eventEmitter, 319 | * | _params.market.marketToken, 320 | * | _params.tokenIn, 321 | * | fees.feeReceiverAmount, 322 | | Keys.DEPOSIT_FEE_TYPE 323 | | ); 324 | | 325 | * | FeeUtils.incrementClaimableUiFeeAmount( 326 | * | params.dataStore, 327 | * | params.eventEmitter, 328 | * | _params.uiFeeReceiver, 329 | * | _params.market.marketToken, 330 | * | _params.tokenIn, 331 | * | fees.uiFeeAmount, 332 | | Keys.UI_DEPOSIT_FEE_TYPE 333 | | ); 334 | | 335 | * | SwapPricingUtils.emitSwapFeesCollected( 336 | * | params.eventEmitter, 337 | * | params.key, 338 | * | _params.market.marketToken, 339 | * | _params.tokenIn, 340 | * | _params.tokenInPrice.min, 341 | | Keys.DEPOSIT_FEE_TYPE, 342 | * | fees 343 | | ); 344 | | 345 | * | uint256 mintAmount; 346 | | 347 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 348 | * | params.dataStore, 349 | * | _params.market, 350 | * | params.oracle.getPrimaryPrice(_params.market.indexToken), 351 | * | _params.tokenIn == _params.market.longToken ? _params.tokenInPrice : _params.tokenOutPrice, 352 | * | _params.tokenIn == _params.market.shortToken ? _params.tokenInPrice : _params.tokenOutPrice, 353 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 354 | * | true 355 | | ); 356 | | 357 | * | if (poolValueInfo.poolValue < 0) { 358 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue); 359 | | } 360 | | 361 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256(); 362 | | 363 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(_params.market.marketToken))); 364 | | 365 | * | if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) { 366 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue); 367 | | } 368 | | 369 | * | MarketEventUtils.emitMarketPoolValueInfo( 370 | * | params.eventEmitter, 371 | * | params.key, 372 | * | _params.market.marketToken, 373 | * | poolValueInfo, 374 | * | marketTokensSupply 375 | | ); 376 | | 377 | | // the poolValue and marketTokensSupply is cached for the mintAmount calculation below 378 | | // so the effect of any positive price impact on the poolValue and marketTokensSupply 379 | | // would not be accounted for 380 | | // 381 | | // for most cases, this should not be an issue, since the poolValue and marketTokensSupply 382 | | // should have been proportionately increased 383 | | // 384 | | // e.g. if the poolValue is $100 and marketTokensSupply is 100, and there is a positive price impact 385 | | // of $10, the poolValue should have increased by $10 and the marketTokensSupply should have been increased by 10 386 | | // 387 | | // there is a case where this may be an issue which is when all tokens are withdrawn from an existing market 388 | | // and the marketTokensSupply is reset to zero, but the poolValue is not entirely zero 389 | | // the case where this happens should be very rare and during withdrawal the poolValue should be close to zero 390 | | // 391 | | // however, in case this occurs, the usdToMarketTokenAmount will mint an additional number of market tokens 392 | | // proportional to the existing poolValue 393 | | // 394 | | // since the poolValue and marketTokensSupply is cached, this could occur once during positive price impact 395 | | // and again when calculating the mintAmount 396 | | // 397 | | // to avoid this, set the priceImpactUsd to be zero for this case 398 | * | if (_params.priceImpactUsd > 0 && marketTokensSupply == 0) { 399 | | _params.priceImpactUsd = 0; 400 | | } 401 | | 402 | * | if (_params.priceImpactUsd > 0) { 403 | | // when there is a positive price impact factor, 404 | | // tokens from the swap impact pool are used to mint additional market tokens for the user 405 | | // for example, if 50,000 USDC is deposited and there is a positive price impact 406 | | // an additional 0.005 ETH may be used to mint market tokens 407 | | // the swap impact pool is decreased by the used amount 408 | | // 409 | | // priceImpactUsd is calculated based on pricing assuming only depositAmount of tokenIn 410 | | // was added to the pool 411 | | // since impactAmount of tokenOut is added to the pool here, the calculation of 412 | | // the price impact would not be entirely accurate 413 | | // 414 | | // it is possible that the addition of the positive impact amount of tokens into the pool 415 | | // could increase the imbalance of the pool, for most cases this should not be a significant 416 | | // change compared to the improvement of balance from the actual deposit 417 | | (int256 positiveImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap( 418 | | params.dataStore, 419 | | params.eventEmitter, 420 | | _params.market.marketToken, 421 | | _params.tokenOut, 422 | | _params.tokenOutPrice, 423 | | _params.priceImpactUsd 424 | | ); 425 | | 426 | | // calculate the usd amount using positiveImpactAmount since it may 427 | | // be capped by the max available amount in the impact pool 428 | | // use tokenOutPrice.max to get the USD value since the positiveImpactAmount 429 | | // was calculated using a USD value divided by tokenOutPrice.max 430 | | // 431 | | // for the initial deposit, the pool value and token supply would be zero 432 | | // so the market token price is treated as 1 USD 433 | | // 434 | | // it is possible for the pool value to be more than zero and the token supply 435 | | // to be zero, in that case, the market token price is also treated as 1 USD 436 | | mintAmount += MarketUtils.usdToMarketTokenAmount( 437 | | positiveImpactAmount.toUint256() * _params.tokenOutPrice.max, 438 | | poolValue, 439 | | marketTokensSupply 440 | | ); 441 | | 442 | | // deposit the token out, that was withdrawn from the impact pool, to mint market tokens 443 | | MarketUtils.applyDeltaToPoolAmount( 444 | | params.dataStore, 445 | | params.eventEmitter, 446 | | _params.market, 447 | | _params.tokenOut, 448 | | positiveImpactAmount 449 | | ); 450 | | 451 | | // MarketUtils.validatePoolUsdForDeposit is not called here 452 | | // this is to prevent unnecessary reverts 453 | | // for example, if the pool's long token is close to the deposit cap 454 | | // but the short token is not close to the cap, depositing the short 455 | | // token can lead to a positive price impact which can cause the 456 | | // long token's deposit cap to be exceeded 457 | | // in this case, it is preferrable that the pool can still be 458 | | // rebalanced even if the deposit cap may be exceeded 459 | | 460 | | MarketUtils.validatePoolAmount( 461 | | params.dataStore, 462 | | _params.market, 463 | | _params.tokenOut 464 | | ); 465 | | } 466 | | 467 | * | if (_params.priceImpactUsd < 0) { 468 | | // when there is a negative price impact factor, 469 | | // less of the deposit amount is used to mint market tokens 470 | | // for example, if 10 ETH is deposited and there is a negative price impact 471 | | // only 9.995 ETH may be used to mint market tokens 472 | | // the remaining 0.005 ETH will be stored in the swap impact pool 473 | | (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap( 474 | | params.dataStore, 475 | | params.eventEmitter, 476 | | _params.market.marketToken, 477 | | _params.tokenIn, 478 | | _params.tokenInPrice, 479 | | _params.priceImpactUsd 480 | | ); 481 | | 482 | | fees.amountAfterFees -= (-negativeImpactAmount).toUint256(); 483 | | } 484 | | 485 | * | mintAmount += MarketUtils.usdToMarketTokenAmount( 486 | * | fees.amountAfterFees * _params.tokenInPrice.min, 487 | * | poolValue, 488 | * | marketTokensSupply 489 | | ); 490 | | 491 | * | MarketUtils.applyDeltaToPoolAmount( 492 | * | params.dataStore, 493 | * | params.eventEmitter, 494 | * | _params.market, 495 | * | _params.tokenIn, 496 | * | (fees.amountAfterFees + fees.feeAmountForPool).toInt256() 497 | | ); 498 | | 499 | * | MarketUtils.validatePoolUsdForDeposit( 500 | * | params.dataStore, 501 | * | _params.market, 502 | * | _params.tokenIn, 503 | * | _params.tokenInPrice.max 504 | | ); 505 | | 506 | * | MarketUtils.validatePoolAmount( 507 | * | params.dataStore, 508 | * | _params.market, 509 | * | _params.tokenIn 510 | | ); 511 | | 512 | * | MarketToken(payable(_params.market.marketToken)).mint(_params.receiver, mintAmount); 513 | | 514 | * | return mintAmount; 515 | | } 516 | | 517 | * | function swap( 518 | | ExecuteDepositParams memory params, 519 | | address[] memory swapPath, 520 | | address initialToken, 521 | | uint256 inputAmount, 522 | | address market, 523 | | address expectedOutputToken, 524 | | address uiFeeReceiver 525 | * | ) internal returns (uint256) { 526 | * | Market.Props[] memory swapPathMarkets = MarketUtils.getSwapPathMarkets( 527 | * | params.dataStore, 528 | * | swapPath 529 | | ); 530 | | 531 | * | (address outputToken, uint256 outputAmount) = SwapUtils.swap( 532 | * | SwapUtils.SwapParams( 533 | * | params.dataStore, // dataStore 534 | * | params.eventEmitter, // eventEmitter 535 | * | params.oracle, // oracle 536 | * | params.depositVault, // bank 537 | * | params.key, // key 538 | * | initialToken, // tokenIn 539 | * | inputAmount, // amountIn 540 | * | swapPathMarkets, // swapPathMarkets 541 | * | 0, // minOutputAmount 542 | * | market, // receiver 543 | * | uiFeeReceiver, // uiFeeReceiver 544 | * | false // shouldUnwrapNativeToken 545 | | ) 546 | | ); 547 | | 548 | * | if (outputToken != expectedOutputToken) { 549 | | revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken); 550 | | } 551 | | 552 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, swapPathMarkets); 553 | | 554 | * | return outputAmount; 555 | | } 556 | | 557 | | // this method validates that a specified minimum number of market tokens are locked 558 | | // this can be used to help ensure a minimum amount of liquidity for a market 559 | | // this also helps to prevent manipulation of the market token price by the first depositor 560 | | // since it may be possible to deposit a small amount of tokens on the first deposit 561 | | // to cause a high market token price due to rounding of the amount of tokens minted 562 | * | function _validateFirstDeposit( 563 | | ExecuteDepositParams memory params, 564 | | Deposit.Props memory deposit, 565 | | Market.Props memory market 566 | | ) internal view { 567 | * | uint256 initialMarketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken))); 568 | | 569 | | // return if this is not the first deposit 570 | * | if (initialMarketTokensSupply != 0) { return; } 571 | | 572 | | uint256 minMarketTokens = params.dataStore.getUint(Keys.minMarketTokensForFirstDepositKey(market.marketToken)); 573 | | 574 | | // return if there is no minMarketTokens requirement 575 | | if (minMarketTokens == 0) { return; } 576 | | 577 | | if (deposit.receiver() != RECEIVER_FOR_FIRST_DEPOSIT) { 578 | | revert Errors.InvalidReceiverForFirstDeposit(deposit.receiver(), RECEIVER_FOR_FIRST_DEPOSIT); 579 | | } 580 | | 581 | | if (deposit.minMarketTokens() < minMarketTokens) { 582 | | revert Errors.InvalidMinMarketTokensForFirstDeposit(deposit.minMarketTokens(), minMarketTokens); 583 | | } 584 | | } 585 | | } 586 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/error/ErrorUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | * | library ErrorUtils { 6 | | // To get the revert reason, referenced from https://ethereum.stackexchange.com/a/83577 7 | * | function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) { 8 | | // If the result length is less than 68, then the transaction either panicked or failed silently 9 | * | if (result.length < 68) { 10 | * | return ("", false); 11 | | } 12 | | 13 | * | bytes4 errorSelector = getErrorSelectorFromData(result); 14 | | 15 | | // 0x08c379a0 is the selector for Error(string) 16 | | // referenced from https://blog.soliditylang.org/2021/04/21/custom-errors/ 17 | * | if (errorSelector == bytes4(0x08c379a0)) { 18 | | assembly { 19 | * | result := add(result, 0x04) 20 | | } 21 | | 22 | * | return (abi.decode(result, (string)), true); 23 | | } 24 | | 25 | | // error may be a custom error, return an empty string for this case 26 | * | return ("", false); 27 | | } 28 | | 29 | * | function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) { 30 | * | bytes4 errorSelector; 31 | | 32 | | assembly { 33 | * | errorSelector := mload(add(data, 0x20)) 34 | | } 35 | | 36 | * | return errorSelector; 37 | | } 38 | | 39 | | function revertWithParsedMessage(bytes memory result) internal pure { 40 | | (string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result); 41 | | 42 | | if (hasRevertMessage) { 43 | | revert(revertMessage); 44 | | } else { 45 | | revertWithCustomError(result); 46 | | } 47 | | } 48 | | 49 | * | function revertWithCustomError(bytes memory result) internal pure { 50 | | // referenced from https://ethereum.stackexchange.com/a/123588 51 | * | uint256 length = result.length; 52 | | assembly { 53 | * | revert(add(result, 0x20), length) 54 | | } 55 | | } 56 | | } 57 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/error/Errors.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | * | library Errors { 6 | | // AdlHandler errors 7 | | error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl); 8 | | error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor); 9 | | error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl); 10 | | 11 | | // AdlUtils errors 12 | | error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd); 13 | | error AdlNotEnabled(); 14 | | 15 | | // AutoCancelUtils errors 16 | | error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders); 17 | | 18 | | // Bank errors 19 | | error SelfTransferNotSupported(address receiver); 20 | | error InvalidNativeTokenSender(address msgSender); 21 | | 22 | | // BaseHandler errors 23 | | error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType); 24 | | 25 | | // CallbackUtils errors 26 | | error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit); 27 | | error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit); 28 | | 29 | | // Config errors 30 | | error InvalidBaseKey(bytes32 baseKey); 31 | | error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value); 32 | | error InvalidClaimableFactor(uint256 value); 33 | | error PriceFeedAlreadyExistsForToken(address token); 34 | | error DataStreamIdAlreadyExistsForToken(address token); 35 | | error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit); 36 | | 37 | | // Timelock errors 38 | | error ActionAlreadySignalled(); 39 | | error ActionNotSignalled(); 40 | | error SignalTimeNotYetPassed(uint256 signalTime); 41 | | error InvalidTimelockDelay(uint256 timelockDelay); 42 | | error MaxTimelockDelayExceeded(uint256 timelockDelay); 43 | | error InvalidFeeReceiver(address receiver); 44 | | error InvalidOracleSigner(address receiver); 45 | | 46 | | // GlvDepositStoreUtils errors 47 | | error GlvDepositNotFound(bytes32 key); 48 | | // GlvDepositUtils errors 49 | | error EmptyGlvDepositAmounts(); 50 | | error EmptyGlvDeposit(); 51 | | // GlvUtils errors 52 | | error EmptyGlv(address glv); 53 | | error GlvUnsupportedMarket(address glv, address market); 54 | | error GlvDisabledMarket(address glv, address market); 55 | | error GlvMaxMarketTokenBalanceExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd); 56 | | error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount); 57 | | error GlvHasPendingShift(address glv); 58 | | error GlvShiftNotFound(bytes32 shiftKey); 59 | | error GlvInvalidReceiver(address glv, address receiver); 60 | | error GlvInvalidCallbackContract(address glvHandler, address callbackContract); 61 | | error GlvMarketAlreadyExists(address glv, address market); 62 | | error InvalidMarketTokenPrice(address market, int256 price); 63 | | // GlvFactory 64 | | error GlvAlreadyExists(address glv); 65 | | 66 | | // DepositStoreUtils errors 67 | | error DepositNotFound(bytes32 key); 68 | | 69 | | // DepositUtils errors 70 | | error EmptyDeposit(); 71 | | error EmptyDepositAmounts(); 72 | | 73 | | // ExecuteDepositUtils errors 74 | | error MinMarketTokens(uint256 received, uint256 expected); 75 | | error EmptyDepositAmountsAfterSwap(); 76 | | error InvalidPoolValueForDeposit(int256 poolValue); 77 | | error InvalidSwapOutputToken(address outputToken, address expectedOutputToken); 78 | | error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver); 79 | | error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens); 80 | | 81 | | // ExternalHandler errors 82 | | error ExternalCallFailed(bytes data); 83 | | error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength); 84 | | error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength); 85 | | error InvalidExternalCallTarget(address target); 86 | | 87 | | // FeeBatchStoreUtils errors 88 | | error FeeBatchNotFound(bytes32 key); 89 | | 90 | | // FeeDistributor errors 91 | | error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength); 92 | | error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount); 93 | | error InvalidSwapPathForV1(address[] path, address bridgingToken); 94 | | 95 | | // GlpMigrator errors 96 | | error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount); 97 | | error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue); 98 | | 99 | | // GlvHandler errors 100 | | error InvalidGlvDepositInitialShortToken(address initialLongToken, address initialShortToken); 101 | | error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength); 102 | | error MinGlvTokens(uint256 received, uint256 expected); 103 | | 104 | | // OrderHandler errors 105 | | error OrderNotUpdatable(uint256 orderType); 106 | | error InvalidKeeperForFrozenOrder(address keeper); 107 | | 108 | | // FeatureUtils errors 109 | | error DisabledFeature(bytes32 key); 110 | | 111 | | // FeeHandler errors 112 | | error InvalidClaimFeesInput(uint256 marketsLength, uint256 tokensLength); 113 | | 114 | | // GasUtils errors 115 | | error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee); 116 | | error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee); 117 | | error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas); 118 | | error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution); 119 | | error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas); 120 | | 121 | | // MarketFactory errors 122 | | error MarketAlreadyExists(bytes32 salt, address existingMarketAddress); 123 | | 124 | | // MarketStoreUtils errors 125 | | error MarketNotFound(address key); 126 | | 127 | | // MarketUtils errors 128 | | error EmptyMarket(); 129 | | error DisabledMarket(address market); 130 | | error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength); 131 | | error InsufficientPoolAmount(uint256 poolAmount, uint256 amount); 132 | | error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd); 133 | | error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd); 134 | | error UnableToGetOppositeToken(address inputToken, address market); 135 | | error UnexpectedTokenForVirtualInventory(address token, address market); 136 | | error EmptyMarketTokenSupply(); 137 | | error InvalidSwapMarket(address market); 138 | | error UnableToGetCachedTokenPrice(address token, address market); 139 | | error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount); 140 | | error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market); 141 | | error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest); 142 | | error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount); 143 | | error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit); 144 | | error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor); 145 | | error UnableToGetBorrowingFactorEmptyPoolUsd(); 146 | | error UnableToGetFundingFactorEmptyOpenInterest(); 147 | | error InvalidPositionMarket(address market); 148 | | error InvalidCollateralTokenForMarket(address market, address token); 149 | | error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor); 150 | | error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor); 151 | | error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor); 152 | | error EmptyAddressInMarketTokenBalanceValidation(address market, address token); 153 | | error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance); 154 | | error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount); 155 | | error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount); 156 | | error UnexpectedPoolValue(int256 poolValue); 157 | | 158 | | // Oracle errors 159 | | error SequencerDown(); 160 | | error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration); 161 | | error EmptyValidatedPrices(); 162 | | error InvalidOracleProvider(address provider); 163 | | error InvalidOracleProviderForToken(address provider, address expectedProvider); 164 | | error GmEmptySigner(uint256 signerIndex); 165 | | error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength); 166 | | error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength); 167 | | error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber); 168 | | error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber); 169 | | error EmptyDataStreamFeedId(address token); 170 | | error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId); 171 | | error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask); 172 | | error InvalidDataStreamPrices(address token, int192 bid, int192 ask); 173 | | error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp); 174 | | error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange); 175 | | error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners); 176 | | error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners); 177 | | error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber); 178 | | error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice); 179 | | error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice); 180 | | error EmptyChainlinkPriceFeedMultiplier(address token); 181 | | error EmptyDataStreamMultiplier(address token); 182 | | error InvalidFeedPrice(address token, int256 price); 183 | | error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration); 184 | | error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex); 185 | | error InvalidGmOraclePrice(address token); 186 | | error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice); 187 | | error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice); 188 | | error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength); 189 | | error InvalidMinMaxForPrice(address token, uint256 min, uint256 max); 190 | | error EmptyChainlinkPriceFeed(address token); 191 | | error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice); 192 | | error MaxRefPriceDeviationExceeded( 193 | | address token, 194 | | uint256 price, 195 | | uint256 refPrice, 196 | | uint256 maxRefPriceDeviationFactor 197 | | ); 198 | | error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber); 199 | | error EmptyChainlinkPaymentToken(); 200 | | error NonAtomicOracleProvider(address provider); 201 | | 202 | | // OracleModule errors 203 | | error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength); 204 | | error EndOfOracleSimulation(); 205 | | 206 | | // OracleUtils errors 207 | | error InvalidGmSignature(address recoveredSigner, address expectedSigner); 208 | | 209 | | error EmptyPrimaryPrice(address token); 210 | | 211 | | error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp); 212 | | error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime); 213 | | 214 | | // BaseOrderUtils errors 215 | | error EmptyOrder(); 216 | | error UnsupportedOrderType(uint256 orderType); 217 | | error InvalidOrderPrices( 218 | | uint256 primaryPriceMin, 219 | | uint256 primaryPriceMax, 220 | | uint256 triggerPrice, 221 | | uint256 orderType 222 | | ); 223 | | error EmptySizeDeltaInTokens(); 224 | | error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd); 225 | | error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd); 226 | | error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice); 227 | | 228 | | // IncreaseOrderUtils errors 229 | | error UnexpectedPositionState(); 230 | | 231 | | // OrderUtils errors 232 | | error OrderTypeCannotBeCreated(uint256 orderType); 233 | | error OrderAlreadyFrozen(); 234 | | error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit); 235 | | 236 | | // OrderStoreUtils errors 237 | | error OrderNotFound(bytes32 key); 238 | | 239 | | // SwapOrderUtils errors 240 | | error UnexpectedMarket(); 241 | | 242 | | // DecreasePositionCollateralUtils errors 243 | | error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step); 244 | | error InvalidOutputToken(address tokenOut, address expectedTokenOut); 245 | | 246 | | // DecreasePositionUtils errors 247 | | error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd); 248 | | error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd); 249 | | error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType); 250 | | error PositionShouldNotBeLiquidated( 251 | | string reason, 252 | | int256 remainingCollateralUsd, 253 | | int256 minCollateralUsd, 254 | | int256 minCollateralUsdForLeverage 255 | | ); 256 | | 257 | | // IncreasePositionUtils errors 258 | | error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount); 259 | | error InsufficientCollateralUsd(int256 remainingCollateralUsd); 260 | | 261 | | // PositionStoreUtils errors 262 | | error PositionNotFound(bytes32 key); 263 | | 264 | | // PositionUtils errors 265 | | error LiquidatablePosition( 266 | | string reason, 267 | | int256 remainingCollateralUsd, 268 | | int256 minCollateralUsd, 269 | | int256 minCollateralUsdForLeverage 270 | | ); 271 | | 272 | | error EmptyPosition(); 273 | | error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens); 274 | | error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd); 275 | | 276 | | // PositionPricingUtils errors 277 | | error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest); 278 | | error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest); 279 | | 280 | | // ShiftStoreUtils errors 281 | | error ShiftNotFound(bytes32 key); 282 | | 283 | | // ShiftUtils errors 284 | | error EmptyShift(); 285 | | error EmptyShiftAmount(); 286 | | error ShiftFromAndToMarketAreEqual(address market); 287 | | error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken); 288 | | error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken); 289 | | 290 | | // SwapPricingUtils errors 291 | | error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd); 292 | | 293 | | // RoleModule errors 294 | | error Unauthorized(address msgSender, string role); 295 | | 296 | | // RoleStore errors 297 | | error ThereMustBeAtLeastOneRoleAdmin(); 298 | | error ThereMustBeAtLeastOneTimelockMultiSig(); 299 | | 300 | | // ExchangeRouter errors 301 | | error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength); 302 | | error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength); 303 | | error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength); 304 | | error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength); 305 | | 306 | | // SwapUtils errors 307 | | error InvalidTokenIn(address tokenIn, address market); 308 | | error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount); 309 | | error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount); 310 | | error DuplicatedMarketInSwapPath(address market); 311 | | error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount); 312 | | 313 | | // SubaccountRouter errors 314 | | error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver); 315 | | 316 | | // SubaccountUtils errors 317 | | error SubaccountNotAuthorized(address account, address subaccount); 318 | | error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount); 319 | | 320 | | // TokenUtils errors 321 | | error EmptyTokenTranferGasLimit(address token); 322 | | error TokenTransferError(address token, address receiver, uint256 amount); 323 | | error EmptyHoldingAddress(); 324 | | 325 | | // AccountUtils errors 326 | | error EmptyAccount(); 327 | | error EmptyReceiver(); 328 | | 329 | | // Array errors 330 | | error CompactedArrayOutOfBounds( 331 | | uint256[] compactedValues, 332 | | uint256 index, 333 | | uint256 slotIndex, 334 | | string label 335 | | ); 336 | | 337 | | error ArrayOutOfBoundsUint256( 338 | | uint256[] values, 339 | | uint256 index, 340 | | string label 341 | | ); 342 | | 343 | | error ArrayOutOfBoundsBytes( 344 | | bytes[] values, 345 | | uint256 index, 346 | | string label 347 | | ); 348 | | 349 | | // WithdrawalHandler errors 350 | | error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength); 351 | | 352 | | // WithdrawalStoreUtils errors 353 | | error WithdrawalNotFound(bytes32 key); 354 | | 355 | | // WithdrawalUtils errors 356 | | error EmptyWithdrawal(); 357 | | error EmptyWithdrawalAmount(); 358 | | error MinLongTokens(uint256 received, uint256 expected); 359 | | error MinShortTokens(uint256 received, uint256 expected); 360 | | error InsufficientMarketTokens(uint256 balance, uint256 expected); 361 | | error InsufficientWntAmount(uint256 wntAmount, uint256 executionFee); 362 | | error InvalidPoolValueForWithdrawal(int256 poolValue); 363 | | 364 | | // Uint256Mask errors 365 | | error MaskIndexOutOfBounds(uint256 index, string label); 366 | | error DuplicatedIndex(uint256 index, string label); 367 | | } 368 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/event/EventEmitter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../role/RoleModule.sol"; 6 | | import "./EventUtils.sol"; 7 | | 8 | | // @title EventEmitter 9 | | // @dev Contract to emit events 10 | | // This allows main events to be emitted from a single contract 11 | | // Logic contracts can be updated while re-using the same eventEmitter contract 12 | | // Peripheral services like monitoring or analytics would be able to continue 13 | | // to work without an update and without segregating historical data 14 | * | contract EventEmitter is RoleModule { 15 | | event EventLog( 16 | | address msgSender, 17 | | string eventName, 18 | | string indexed eventNameHash, 19 | | EventUtils.EventLogData eventData 20 | | ); 21 | | 22 | | event EventLog1( 23 | | address msgSender, 24 | | string eventName, 25 | | string indexed eventNameHash, 26 | | bytes32 indexed topic1, 27 | | EventUtils.EventLogData eventData 28 | | ); 29 | | 30 | | event EventLog2( 31 | | address msgSender, 32 | | string eventName, 33 | | string indexed eventNameHash, 34 | | bytes32 indexed topic1, 35 | | bytes32 indexed topic2, 36 | | EventUtils.EventLogData eventData 37 | | ); 38 | | 39 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {} 40 | | 41 | | // @dev emit a general event log 42 | | // @param eventName the name of the event 43 | | // @param eventData the event data 44 | * | function emitEventLog( 45 | | string memory eventName, 46 | | EventUtils.EventLogData memory eventData 47 | | ) external onlyController { 48 | * | emit EventLog( 49 | * | msg.sender, 50 | * | eventName, 51 | * | eventName, 52 | * | eventData 53 | | ); 54 | | } 55 | | 56 | | // @dev emit a general event log 57 | | // @param eventName the name of the event 58 | | // @param topic1 topic1 for indexing 59 | | // @param eventData the event data 60 | * | function emitEventLog1( 61 | | string memory eventName, 62 | | bytes32 topic1, 63 | | EventUtils.EventLogData memory eventData 64 | | ) external onlyController { 65 | * | emit EventLog1( 66 | * | msg.sender, 67 | * | eventName, 68 | * | eventName, 69 | * | topic1, 70 | * | eventData 71 | | ); 72 | | } 73 | | 74 | | // @dev emit a general event log 75 | | // @param eventName the name of the event 76 | | // @param topic1 topic1 for indexing 77 | | // @param topic2 topic2 for indexing 78 | | // @param eventData the event data 79 | * | function emitEventLog2( 80 | | string memory eventName, 81 | | bytes32 topic1, 82 | | bytes32 topic2, 83 | | EventUtils.EventLogData memory eventData 84 | | ) external onlyController { 85 | * | emit EventLog2( 86 | * | msg.sender, 87 | * | eventName, 88 | * | eventName, 89 | * | topic1, 90 | * | topic2, 91 | * | eventData 92 | | ); 93 | | } 94 | | // @dev event log for general use 95 | | // @param topic1 event topic 1 96 | | // @param data additional data 97 | | function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController { 98 | | uint256 len = data.length; 99 | | assembly { 100 | | log1(add(data, 32), len, topic1) 101 | | } 102 | | } 103 | | 104 | | // @dev event log for general use 105 | | // @param topic1 event topic 1 106 | | // @param topic2 event topic 2 107 | | // @param data additional data 108 | | function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController { 109 | | uint256 len = data.length; 110 | | assembly { 111 | | log2(add(data, 32), len, topic1, topic2) 112 | | } 113 | | } 114 | | 115 | | // @dev event log for general use 116 | | // @param topic1 event topic 1 117 | | // @param topic2 event topic 2 118 | | // @param topic3 event topic 3 119 | | // @param data additional data 120 | | function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController { 121 | | uint256 len = data.length; 122 | | assembly { 123 | | log3(add(data, 32), len, topic1, topic2, topic3) 124 | | } 125 | | } 126 | | 127 | | // @dev event log for general use 128 | | // @param topic1 event topic 1 129 | | // @param topic2 event topic 2 130 | | // @param topic3 event topic 3 131 | | // @param topic4 event topic 4 132 | | // @param data additional data 133 | | function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController { 134 | | uint256 len = data.length; 135 | | assembly { 136 | | log4(add(data, 32), len, topic1, topic2, topic3, topic4) 137 | | } 138 | | } 139 | | } 140 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/event/EventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | * | library EventUtils { 6 | | struct EmitPositionDecreaseParams { 7 | | bytes32 key; 8 | | address account; 9 | | address market; 10 | | address collateralToken; 11 | | bool isLong; 12 | | } 13 | | 14 | | struct EventLogData { 15 | | AddressItems addressItems; 16 | | UintItems uintItems; 17 | | IntItems intItems; 18 | | BoolItems boolItems; 19 | | Bytes32Items bytes32Items; 20 | | BytesItems bytesItems; 21 | | StringItems stringItems; 22 | | } 23 | | 24 | | struct AddressItems { 25 | | AddressKeyValue[] items; 26 | | AddressArrayKeyValue[] arrayItems; 27 | | } 28 | | 29 | | struct UintItems { 30 | | UintKeyValue[] items; 31 | | UintArrayKeyValue[] arrayItems; 32 | | } 33 | | 34 | | struct IntItems { 35 | | IntKeyValue[] items; 36 | | IntArrayKeyValue[] arrayItems; 37 | | } 38 | | 39 | | struct BoolItems { 40 | | BoolKeyValue[] items; 41 | | BoolArrayKeyValue[] arrayItems; 42 | | } 43 | | 44 | | struct Bytes32Items { 45 | | Bytes32KeyValue[] items; 46 | | Bytes32ArrayKeyValue[] arrayItems; 47 | | } 48 | | 49 | | struct BytesItems { 50 | | BytesKeyValue[] items; 51 | | BytesArrayKeyValue[] arrayItems; 52 | | } 53 | | 54 | | struct StringItems { 55 | | StringKeyValue[] items; 56 | | StringArrayKeyValue[] arrayItems; 57 | | } 58 | | 59 | | struct AddressKeyValue { 60 | | string key; 61 | | address value; 62 | | } 63 | | 64 | | struct AddressArrayKeyValue { 65 | | string key; 66 | | address[] value; 67 | | } 68 | | 69 | | struct UintKeyValue { 70 | | string key; 71 | | uint256 value; 72 | | } 73 | | 74 | | struct UintArrayKeyValue { 75 | | string key; 76 | | uint256[] value; 77 | | } 78 | | 79 | | struct IntKeyValue { 80 | | string key; 81 | | int256 value; 82 | | } 83 | | 84 | | struct IntArrayKeyValue { 85 | | string key; 86 | | int256[] value; 87 | | } 88 | | 89 | | struct BoolKeyValue { 90 | | string key; 91 | | bool value; 92 | | } 93 | | 94 | | struct BoolArrayKeyValue { 95 | | string key; 96 | | bool[] value; 97 | | } 98 | | 99 | | struct Bytes32KeyValue { 100 | | string key; 101 | | bytes32 value; 102 | | } 103 | | 104 | | struct Bytes32ArrayKeyValue { 105 | | string key; 106 | | bytes32[] value; 107 | | } 108 | | 109 | | struct BytesKeyValue { 110 | | string key; 111 | | bytes value; 112 | | } 113 | | 114 | | struct BytesArrayKeyValue { 115 | | string key; 116 | | bytes[] value; 117 | | } 118 | | 119 | | struct StringKeyValue { 120 | | string key; 121 | | string value; 122 | | } 123 | | 124 | | struct StringArrayKeyValue { 125 | | string key; 126 | | string[] value; 127 | | } 128 | | 129 | * | function initItems(AddressItems memory items, uint256 size) internal pure { 130 | * | items.items = new EventUtils.AddressKeyValue[](size); 131 | | } 132 | | 133 | * | function initArrayItems(AddressItems memory items, uint256 size) internal pure { 134 | * | items.arrayItems = new EventUtils.AddressArrayKeyValue[](size); 135 | | } 136 | | 137 | * | function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure { 138 | * | items.items[index].key = key; 139 | * | items.items[index].value = value; 140 | | } 141 | | 142 | * | function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure { 143 | * | items.arrayItems[index].key = key; 144 | * | items.arrayItems[index].value = value; 145 | | } 146 | | 147 | * | function initItems(UintItems memory items, uint256 size) internal pure { 148 | * | items.items = new EventUtils.UintKeyValue[](size); 149 | | } 150 | | 151 | | function initArrayItems(UintItems memory items, uint256 size) internal pure { 152 | | items.arrayItems = new EventUtils.UintArrayKeyValue[](size); 153 | | } 154 | | 155 | * | function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure { 156 | * | items.items[index].key = key; 157 | * | items.items[index].value = value; 158 | | } 159 | | 160 | | function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure { 161 | | items.arrayItems[index].key = key; 162 | | items.arrayItems[index].value = value; 163 | | } 164 | | 165 | * | function initItems(IntItems memory items, uint256 size) internal pure { 166 | * | items.items = new EventUtils.IntKeyValue[](size); 167 | | } 168 | | 169 | | function initArrayItems(IntItems memory items, uint256 size) internal pure { 170 | | items.arrayItems = new EventUtils.IntArrayKeyValue[](size); 171 | | } 172 | | 173 | * | function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure { 174 | * | items.items[index].key = key; 175 | * | items.items[index].value = value; 176 | | } 177 | | 178 | | function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure { 179 | | items.arrayItems[index].key = key; 180 | | items.arrayItems[index].value = value; 181 | | } 182 | | 183 | * | function initItems(BoolItems memory items, uint256 size) internal pure { 184 | * | items.items = new EventUtils.BoolKeyValue[](size); 185 | | } 186 | | 187 | | function initArrayItems(BoolItems memory items, uint256 size) internal pure { 188 | | items.arrayItems = new EventUtils.BoolArrayKeyValue[](size); 189 | | } 190 | | 191 | * | function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure { 192 | * | items.items[index].key = key; 193 | * | items.items[index].value = value; 194 | | } 195 | | 196 | | function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure { 197 | | items.arrayItems[index].key = key; 198 | | items.arrayItems[index].value = value; 199 | | } 200 | | 201 | * | function initItems(Bytes32Items memory items, uint256 size) internal pure { 202 | * | items.items = new EventUtils.Bytes32KeyValue[](size); 203 | | } 204 | | 205 | | function initArrayItems(Bytes32Items memory items, uint256 size) internal pure { 206 | | items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size); 207 | | } 208 | | 209 | * | function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure { 210 | * | items.items[index].key = key; 211 | * | items.items[index].value = value; 212 | | } 213 | | 214 | | function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure { 215 | | items.arrayItems[index].key = key; 216 | | items.arrayItems[index].value = value; 217 | | } 218 | | 219 | * | function initItems(BytesItems memory items, uint256 size) internal pure { 220 | * | items.items = new EventUtils.BytesKeyValue[](size); 221 | | } 222 | | 223 | | function initArrayItems(BytesItems memory items, uint256 size) internal pure { 224 | | items.arrayItems = new EventUtils.BytesArrayKeyValue[](size); 225 | | } 226 | | 227 | * | function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure { 228 | * | items.items[index].key = key; 229 | * | items.items[index].value = value; 230 | | } 231 | | 232 | | function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure { 233 | | items.arrayItems[index].key = key; 234 | | items.arrayItems[index].value = value; 235 | | } 236 | | 237 | * | function initItems(StringItems memory items, uint256 size) internal pure { 238 | * | items.items = new EventUtils.StringKeyValue[](size); 239 | | } 240 | | 241 | | function initArrayItems(StringItems memory items, uint256 size) internal pure { 242 | | items.arrayItems = new EventUtils.StringArrayKeyValue[](size); 243 | | } 244 | | 245 | * | function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure { 246 | * | items.items[index].key = key; 247 | * | items.items[index].value = value; 248 | | } 249 | | 250 | | function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure { 251 | | items.arrayItems[index].key = key; 252 | | items.arrayItems[index].value = value; 253 | | } 254 | | } 255 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/AdlHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderHandler.sol"; 6 | | 7 | | // @title AdlHandler 8 | | // @dev Contract to handle adls 9 | * | contract AdlHandler is BaseOrderHandler { 10 | | using SafeCast for uint256; 11 | | using SafeCast for int256; 12 | | using Order for Order.Props; 13 | | using Array for uint256[]; 14 | | 15 | | // @dev ExecuteAdlCache struct used in executeAdl to avoid 16 | | // stack too deep errors 17 | | struct ExecuteAdlCache { 18 | | uint256 startingGas; 19 | | bytes32 key; 20 | | bool shouldAllowAdl; 21 | | uint256 maxPnlFactorForAdl; 22 | | int256 pnlToPoolFactor; 23 | | int256 nextPnlToPoolFactor; 24 | | uint256 minPnlFactorForAdl; 25 | | } 26 | | 27 | | constructor( 28 | | RoleStore _roleStore, 29 | | DataStore _dataStore, 30 | | EventEmitter _eventEmitter, 31 | | Oracle _oracle, 32 | | OrderVault _orderVault, 33 | | SwapHandler _swapHandler, 34 | | IReferralStorage _referralStorage 35 | | ) BaseOrderHandler( 36 | | _roleStore, 37 | | _dataStore, 38 | | _eventEmitter, 39 | | _oracle, 40 | | _orderVault, 41 | | _swapHandler, 42 | | _referralStorage 43 | | ) {} 44 | | 45 | | // @dev checks the ADL state to update the isAdlEnabled flag 46 | | // @param market the market to check 47 | | // @param isLong whether to check the long or short side 48 | | // @param oracleParams OracleUtils.SetPricesParams 49 | * | function updateAdlState( 50 | | address market, 51 | | bool isLong, 52 | | OracleUtils.SetPricesParams calldata oracleParams 53 | | ) external 54 | | globalNonReentrant 55 | | onlyAdlKeeper 56 | * | withOraclePrices(oracleParams) 57 | | { 58 | * | AdlUtils.updateAdlState( 59 | * | dataStore, 60 | * | eventEmitter, 61 | * | oracle, 62 | * | market, 63 | * | isLong 64 | | ); 65 | | } 66 | | 67 | | // @dev auto-deleverages a position 68 | | // there is no validation that ADL is executed in order of position profit 69 | | // or position size, this is due to the limitation of the gas overhead 70 | | // required to check this ordering 71 | | // 72 | | // ADL keepers could be separately incentivised using a rebate based on 73 | | // position profit, this is not implemented within the contracts at the moment 74 | | // 75 | | // @param account the position's account 76 | | // @param market the position's market 77 | | // @param collateralToken the position's collateralToken 78 | | // @param isLong whether the position is long or short 79 | | // @param sizeDeltaUsd the size to reduce the position by 80 | | // @param oracleParams OracleUtils.SetPricesParams 81 | * | function executeAdl( 82 | | address account, 83 | | address market, 84 | | address collateralToken, 85 | | bool isLong, 86 | | uint256 sizeDeltaUsd, 87 | | OracleUtils.SetPricesParams calldata oracleParams 88 | | ) external 89 | | globalNonReentrant 90 | | onlyAdlKeeper 91 | * | withOraclePrices(oracleParams) 92 | * | { 93 | * | ExecuteAdlCache memory cache; 94 | | 95 | * | cache.startingGas = gasleft(); 96 | | 97 | * | AdlUtils.validateAdl( 98 | * | dataStore, 99 | * | oracle, 100 | * | market, 101 | * | isLong 102 | | ); 103 | | 104 | * | (cache.shouldAllowAdl, cache.pnlToPoolFactor, cache.maxPnlFactorForAdl) = MarketUtils.isPnlFactorExceeded( 105 | * | dataStore, 106 | * | oracle, 107 | * | market, 108 | * | isLong, 109 | | Keys.MAX_PNL_FACTOR_FOR_ADL 110 | | ); 111 | | 112 | * | if (!cache.shouldAllowAdl) { 113 | | revert Errors.AdlNotRequired(cache.pnlToPoolFactor, cache.maxPnlFactorForAdl); 114 | | } 115 | | 116 | * | cache.key = AdlUtils.createAdlOrder( 117 | * | AdlUtils.CreateAdlOrderParams( 118 | * | dataStore, 119 | * | eventEmitter, 120 | * | account, 121 | * | market, 122 | * | collateralToken, 123 | * | isLong, 124 | * | sizeDeltaUsd, 125 | * | Chain.currentBlockNumber(), // updatedAtBlock 126 | * | oracle.minTimestamp() // updatedAtTime 127 | | ) 128 | | ); 129 | | 130 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, cache.key); 131 | | 132 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams( 133 | * | cache.key, 134 | * | order, 135 | * | msg.sender, 136 | * | cache.startingGas, 137 | * | Order.SecondaryOrderType.Adl 138 | | ); 139 | | 140 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeAdlFeatureDisabledKey(address(this), uint256(params.order.orderType()))); 141 | | 142 | * | ExecuteOrderUtils.executeOrder(params); 143 | | 144 | | // validate that the ratio of pending pnl to pool value was decreased 145 | * | cache.nextPnlToPoolFactor = MarketUtils.getPnlToPoolFactor(dataStore, oracle, market, isLong, true); 146 | * | if (cache.nextPnlToPoolFactor >= cache.pnlToPoolFactor) { 147 | | revert Errors.InvalidAdl(cache.nextPnlToPoolFactor, cache.pnlToPoolFactor); 148 | | } 149 | | 150 | * | cache.minPnlFactorForAdl = MarketUtils.getMinPnlFactorAfterAdl(dataStore, market, isLong); 151 | | 152 | * | if (cache.nextPnlToPoolFactor < cache.minPnlFactorForAdl.toInt256()) { 153 | | revert Errors.PnlOvercorrected(cache.nextPnlToPoolFactor, cache.minPnlFactorForAdl); 154 | | } 155 | | } 156 | | } 157 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/BaseHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../feature/FeatureUtils.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | import "../oracle/Oracle.sol"; 8 | | import "../oracle/OracleModule.sol"; 9 | | import "../role/RoleModule.sol"; 10 | | import "../utils/GlobalReentrancyGuard.sol"; 11 | | 12 | | contract BaseHandler is RoleModule, GlobalReentrancyGuard, OracleModule { 13 | | EventEmitter public immutable eventEmitter; 14 | | 15 | | constructor( 16 | | RoleStore _roleStore, 17 | | DataStore _dataStore, 18 | | EventEmitter _eventEmitter, 19 | | Oracle _oracle 20 | | ) RoleModule(_roleStore) GlobalReentrancyGuard(_dataStore) OracleModule(_oracle) { 21 | | eventEmitter = _eventEmitter; 22 | | } 23 | | 24 | * | receive() external payable { 25 | * | address wnt = dataStore.getAddress(Keys.WNT); 26 | * | if (msg.sender != wnt) { 27 | | revert Errors.InvalidNativeTokenSender(msg.sender); 28 | | } 29 | | } 30 | | 31 | * | function validateRequestCancellation( 32 | | uint256 createdAtTime, 33 | | string memory requestType 34 | * | ) internal view { 35 | * | uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 36 | * | uint256 requestAge = Chain.currentTimestamp() - createdAtTime; 37 | * | if (requestAge < requestExpirationTime) { 38 | * | revert Errors.RequestNotYetCancellable(requestAge, requestExpirationTime, requestType); 39 | | } 40 | | } 41 | | } 42 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/BaseOrderHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseHandler.sol"; 6 | | import "../callback/CallbackUtils.sol"; 7 | | 8 | | import "../adl/AdlUtils.sol"; 9 | | import "../liquidation/LiquidationUtils.sol"; 10 | | 11 | | import "../market/Market.sol"; 12 | | import "../market/MarketToken.sol"; 13 | | 14 | | import "../order/Order.sol"; 15 | | import "../order/OrderVault.sol"; 16 | | import "../order/OrderUtils.sol"; 17 | | import "../order/ExecuteOrderUtils.sol"; 18 | | 19 | | import "../referral/IReferralStorage.sol"; 20 | | 21 | | // @title BaseOrderHandler 22 | | // @dev Base contract for shared order handler functions 23 | | contract BaseOrderHandler is BaseHandler { 24 | | using SafeCast for uint256; 25 | | using Order for Order.Props; 26 | | using Array for uint256[]; 27 | | 28 | | OrderVault public immutable orderVault; 29 | | SwapHandler public immutable swapHandler; 30 | | IReferralStorage public immutable referralStorage; 31 | | 32 | | constructor( 33 | | RoleStore _roleStore, 34 | | DataStore _dataStore, 35 | | EventEmitter _eventEmitter, 36 | | Oracle _oracle, 37 | | OrderVault _orderVault, 38 | | SwapHandler _swapHandler, 39 | | IReferralStorage _referralStorage 40 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) { 41 | | orderVault = _orderVault; 42 | | swapHandler = _swapHandler; 43 | | referralStorage = _referralStorage; 44 | | } 45 | | 46 | | // @dev get the BaseOrderUtils.ExecuteOrderParams to execute an order 47 | | // @return the required BaseOrderUtils.ExecuteOrderParams params to execute the order 48 | * | function _getExecuteOrderParams( 49 | | bytes32 key, 50 | | Order.Props memory order, 51 | | address keeper, 52 | | uint256 startingGas, 53 | | Order.SecondaryOrderType secondaryOrderType 54 | * | ) internal view returns (BaseOrderUtils.ExecuteOrderParams memory) { 55 | * | BaseOrderUtils.ExecuteOrderParams memory params; 56 | | 57 | * | params.key = key; 58 | * | params.order = order; 59 | * | params.swapPathMarkets = MarketUtils.getSwapPathMarkets( 60 | * | dataStore, 61 | * | params.order.swapPath() 62 | | ); 63 | | 64 | * | params.contracts.dataStore = dataStore; 65 | * | params.contracts.eventEmitter = eventEmitter; 66 | * | params.contracts.orderVault = orderVault; 67 | * | params.contracts.oracle = oracle; 68 | * | params.contracts.swapHandler = swapHandler; 69 | * | params.contracts.referralStorage = referralStorage; 70 | | 71 | * | params.minOracleTimestamp = oracle.minTimestamp(); 72 | * | params.maxOracleTimestamp = oracle.maxTimestamp(); 73 | | 74 | * | if (params.order.market() != address(0)) { 75 | * | params.market = MarketUtils.getEnabledMarket(params.contracts.dataStore, params.order.market()); 76 | | } 77 | | 78 | * | params.keeper = keeper; 79 | * | params.startingGas = startingGas; 80 | | 81 | * | params.secondaryOrderType = secondaryOrderType; 82 | | 83 | * | return params; 84 | | } 85 | | } 86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/DepositHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseHandler.sol"; 6 | | 7 | | import "../market/Market.sol"; 8 | | import "../market/MarketToken.sol"; 9 | | 10 | | import "../deposit/Deposit.sol"; 11 | | import "../deposit/DepositVault.sol"; 12 | | import "../deposit/DepositUtils.sol"; 13 | | import "../deposit/ExecuteDepositUtils.sol"; 14 | | 15 | | import "./IDepositHandler.sol"; 16 | | 17 | | // @title DepositHandler 18 | | // @dev Contract to handle creation, execution and cancellation of deposits 19 | * | contract DepositHandler is IDepositHandler, BaseHandler { 20 | | using Deposit for Deposit.Props; 21 | | 22 | | DepositVault public immutable depositVault; 23 | | 24 | | constructor( 25 | | RoleStore _roleStore, 26 | | DataStore _dataStore, 27 | | EventEmitter _eventEmitter, 28 | | Oracle _oracle, 29 | | DepositVault _depositVault 30 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) { 31 | | depositVault = _depositVault; 32 | | } 33 | | 34 | | // @dev creates a deposit in the deposit store 35 | | // @param account the depositing account 36 | | // @param params DepositUtils.CreateDepositParams 37 | * | function createDeposit( 38 | | address account, 39 | | DepositUtils.CreateDepositParams calldata params 40 | * | ) external override globalNonReentrant onlyController returns (bytes32) { 41 | * | FeatureUtils.validateFeature(dataStore, Keys.createDepositFeatureDisabledKey(address(this))); 42 | | 43 | * | return DepositUtils.createDeposit( 44 | * | dataStore, 45 | * | eventEmitter, 46 | * | depositVault, 47 | * | account, 48 | * | params 49 | | ); 50 | | } 51 | | 52 | | // @dev cancels a deposit 53 | | // @param key the deposit key 54 | * | function cancelDeposit(bytes32 key) external override globalNonReentrant onlyController { 55 | * | uint256 startingGas = gasleft(); 56 | | 57 | * | DataStore _dataStore = dataStore; 58 | * | Deposit.Props memory deposit = DepositStoreUtils.get(_dataStore, key); 59 | | 60 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelDepositFeatureDisabledKey(address(this))); 61 | | 62 | * | validateRequestCancellation( 63 | * | deposit.updatedAtTime(), 64 | | "Deposit" 65 | | ); 66 | | 67 | * | DepositUtils.cancelDeposit( 68 | * | _dataStore, 69 | * | eventEmitter, 70 | * | depositVault, 71 | * | key, 72 | * | deposit.account(), 73 | * | startingGas, 74 | * | Keys.USER_INITIATED_CANCEL, 75 | | "" 76 | | ); 77 | | } 78 | | 79 | | // @dev executes a deposit 80 | | // @param key the key of the deposit to execute 81 | | // @param oracleParams OracleUtils.SetPricesParams 82 | * | function executeDeposit( 83 | | bytes32 key, 84 | | OracleUtils.SetPricesParams calldata oracleParams 85 | | ) external 86 | | globalNonReentrant 87 | | onlyOrderKeeper 88 | * | withOraclePrices(oracleParams) 89 | * | { 90 | * | uint256 startingGas = gasleft(); 91 | | 92 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key); 93 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteDepositGasLimit(dataStore, deposit); 94 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit); 95 | | 96 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas); 97 | | 98 | * | try this._executeDeposit{ gas: executionGas }( 99 | * | key, 100 | * | deposit, 101 | * | msg.sender 102 | | ) { 103 | * | } catch (bytes memory reasonBytes) { 104 | * | _handleDepositError( 105 | * | key, 106 | * | startingGas, 107 | * | reasonBytes 108 | | ); 109 | | } 110 | | } 111 | | 112 | | // @dev simulate execution of a deposit to check for any errors 113 | | // @param key the deposit key 114 | | // @param params OracleUtils.SimulatePricesParams 115 | | function simulateExecuteDeposit( 116 | | bytes32 key, 117 | | OracleUtils.SimulatePricesParams memory params 118 | | ) external 119 | | override 120 | | onlyController 121 | | withSimulatedOraclePrices(params) 122 | | globalNonReentrant 123 | | { 124 | | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key); 125 | | 126 | | this._executeDeposit( 127 | | key, 128 | | deposit, 129 | | msg.sender 130 | | ); 131 | | } 132 | | 133 | | // @dev executes a deposit 134 | | // @param oracleParams OracleUtils.SetPricesParams 135 | | // @param keeper the keeper executing the deposit 136 | | // @param startingGas the starting gas 137 | * | function _executeDeposit( 138 | | bytes32 key, 139 | | Deposit.Props memory deposit, 140 | | address keeper 141 | * | ) external onlySelf { 142 | * | uint256 startingGas = gasleft(); 143 | | 144 | * | FeatureUtils.validateFeature(dataStore, Keys.executeDepositFeatureDisabledKey(address(this))); 145 | | 146 | * | ExecuteDepositUtils.ExecuteDepositParams memory params = ExecuteDepositUtils.ExecuteDepositParams( 147 | * | dataStore, 148 | * | eventEmitter, 149 | * | depositVault, 150 | * | oracle, 151 | * | key, 152 | * | keeper, 153 | * | startingGas, 154 | * | ISwapPricingUtils.SwapPricingType.TwoStep, 155 | * | true // includeVirtualInventoryImpact 156 | | ); 157 | | 158 | * | ExecuteDepositUtils.executeDeposit(params, deposit); 159 | | } 160 | | 161 | | // @dev handle errors from deposits 162 | | // @param key the deposit key 163 | | // @param startingGas the starting gas of the txn 164 | | // @param reasonBytes the reason bytes of the error 165 | * | function _handleDepositError( 166 | | bytes32 key, 167 | | uint256 startingGas, 168 | | bytes memory reasonBytes 169 | * | ) internal { 170 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes); 171 | | 172 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes); 173 | | 174 | * | if ( 175 | * | OracleUtils.isOracleError(errorSelector) || 176 | * | errorSelector == Errors.DisabledFeature.selector || 177 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector 178 | | ) { 179 | * | ErrorUtils.revertWithCustomError(reasonBytes); 180 | | } 181 | | 182 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 183 | | 184 | * | DepositUtils.cancelDeposit( 185 | * | dataStore, 186 | * | eventEmitter, 187 | * | depositVault, 188 | * | key, 189 | * | msg.sender, 190 | * | startingGas, 191 | * | reason, 192 | * | reasonBytes 193 | | ); 194 | | } 195 | | } 196 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IDepositHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../deposit/DepositUtils.sol"; 6 | | import "../oracle/OracleUtils.sol"; 7 | | 8 | | interface IDepositHandler { 9 | | function createDeposit(address account, DepositUtils.CreateDepositParams calldata params) external returns (bytes32); 10 | | function cancelDeposit(bytes32 key) external; 11 | | function simulateExecuteDeposit( 12 | | bytes32 key, 13 | | OracleUtils.SimulatePricesParams memory params 14 | | ) external; 15 | | } 16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IGlvHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../glv/GlvDepositUtils.sol"; 6 | | import "../oracle/OracleUtils.sol"; 7 | | 8 | | interface IGlvHandler { 9 | | function createGlvDeposit(address account, GlvDepositUtils.CreateGlvDepositParams calldata params) external returns (bytes32); 10 | | function cancelGlvDeposit(bytes32 key) external; 11 | | function simulateExecuteGlvDeposit( 12 | | bytes32 key, 13 | | OracleUtils.SimulatePricesParams memory params 14 | | ) external; 15 | | } 16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IOrderHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../order/IBaseOrderUtils.sol"; 6 | | import "../oracle/OracleUtils.sol"; 7 | | 8 | | interface IOrderHandler { 9 | | function createOrder(address account, IBaseOrderUtils.CreateOrderParams calldata params) external returns (bytes32); 10 | | 11 | | function simulateExecuteOrder(bytes32 key, OracleUtils.SimulatePricesParams memory params) external; 12 | | 13 | | function updateOrder( 14 | | bytes32 key, 15 | | uint256 sizeDeltaUsd, 16 | | uint256 acceptablePrice, 17 | | uint256 triggerPrice, 18 | | uint256 minOutputAmount, 19 | | bool autoCancel, 20 | | Order.Props memory order 21 | | ) external; 22 | | 23 | | function cancelOrder(bytes32 key) external; 24 | | } 25 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IShiftHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../shift/ShiftUtils.sol"; 6 | | import "../oracle/OracleUtils.sol"; 7 | | 8 | | interface IShiftHandler { 9 | | function createShift(address account, ShiftUtils.CreateShiftParams calldata params) external returns (bytes32); 10 | | function cancelShift(bytes32 key) external; 11 | | function simulateExecuteShift(bytes32 key, OracleUtils.SimulatePricesParams memory params) external; 12 | | } 13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/IWithdrawalHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../withdrawal/WithdrawalUtils.sol"; 6 | | import "../oracle/OracleUtils.sol"; 7 | | import "../pricing/ISwapPricingUtils.sol"; 8 | | 9 | | interface IWithdrawalHandler { 10 | | function createWithdrawal(address account, WithdrawalUtils.CreateWithdrawalParams calldata params) external returns (bytes32); 11 | | function cancelWithdrawal(bytes32 key) external; 12 | | function executeAtomicWithdrawal( 13 | | address account, 14 | | WithdrawalUtils.CreateWithdrawalParams calldata params, 15 | | OracleUtils.SetPricesParams calldata oracleParams 16 | | ) external; 17 | | function simulateExecuteWithdrawal( 18 | | bytes32 key, 19 | | OracleUtils.SimulatePricesParams memory params, 20 | | ISwapPricingUtils.SwapPricingType swapPricingType 21 | | ) external; 22 | | } 23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/LiquidationHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderHandler.sol"; 6 | | 7 | | // @title LiquidationHandler 8 | | // @dev Contract to handle liquidations 9 | * | contract LiquidationHandler is BaseOrderHandler { 10 | | using SafeCast for uint256; 11 | | using Order for Order.Props; 12 | | using Array for uint256[]; 13 | | 14 | | constructor( 15 | | RoleStore _roleStore, 16 | | DataStore _dataStore, 17 | | EventEmitter _eventEmitter, 18 | | Oracle _oracle, 19 | | OrderVault _orderVault, 20 | | SwapHandler _swapHandler, 21 | | IReferralStorage _referralStorage 22 | | ) BaseOrderHandler( 23 | | _roleStore, 24 | | _dataStore, 25 | | _eventEmitter, 26 | | _oracle, 27 | | _orderVault, 28 | | _swapHandler, 29 | | _referralStorage 30 | | ) {} 31 | | 32 | | // @dev executes a position liquidation 33 | | // @param account the account of the position to liquidate 34 | | // @param market the position's market 35 | | // @param collateralToken the position's collateralToken 36 | | // @param isLong whether the position is long or short 37 | | // @param oracleParams OracleUtils.SetPricesParams 38 | * | function executeLiquidation( 39 | | address account, 40 | | address market, 41 | | address collateralToken, 42 | | bool isLong, 43 | | OracleUtils.SetPricesParams calldata oracleParams 44 | | ) external 45 | | globalNonReentrant 46 | | onlyLiquidationKeeper 47 | * | withOraclePrices(oracleParams) 48 | * | { 49 | * | uint256 startingGas = gasleft(); 50 | | 51 | * | oracle.validateSequencerUp(); 52 | | 53 | * | bytes32 key = LiquidationUtils.createLiquidationOrder( 54 | * | dataStore, 55 | * | eventEmitter, 56 | * | account, 57 | * | market, 58 | * | collateralToken, 59 | * | isLong 60 | | ); 61 | | 62 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 63 | | 64 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams( 65 | * | key, 66 | * | order, 67 | * | msg.sender, 68 | * | startingGas, 69 | * | Order.SecondaryOrderType.None 70 | | ); 71 | | 72 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType()))); 73 | | 74 | * | ExecuteOrderUtils.executeOrder(params); 75 | | } 76 | | } 77 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/OrderHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderHandler.sol"; 6 | | import "../error/ErrorUtils.sol"; 7 | | import "./IOrderHandler.sol"; 8 | | 9 | | // @title OrderHandler 10 | | // @dev Contract to handle creation, execution and cancellation of orders 11 | * | contract OrderHandler is IOrderHandler, BaseOrderHandler { 12 | | using SafeCast for uint256; 13 | | using Order for Order.Props; 14 | | using Array for uint256[]; 15 | | 16 | | constructor( 17 | | RoleStore _roleStore, 18 | | DataStore _dataStore, 19 | | EventEmitter _eventEmitter, 20 | | Oracle _oracle, 21 | | OrderVault _orderVault, 22 | | SwapHandler _swapHandler, 23 | | IReferralStorage _referralStorage 24 | | ) BaseOrderHandler( 25 | | _roleStore, 26 | | _dataStore, 27 | | _eventEmitter, 28 | | _oracle, 29 | | _orderVault, 30 | | _swapHandler, 31 | | _referralStorage 32 | | ) {} 33 | | 34 | | // @dev creates an order in the order store 35 | | // @param account the order's account 36 | | // @param params BaseOrderUtils.CreateOrderParams 37 | * | function createOrder( 38 | | address account, 39 | | IBaseOrderUtils.CreateOrderParams calldata params 40 | * | ) external override globalNonReentrant onlyController returns (bytes32) { 41 | * | FeatureUtils.validateFeature(dataStore, Keys.createOrderFeatureDisabledKey(address(this), uint256(params.orderType))); 42 | | 43 | * | return OrderUtils.createOrder( 44 | * | dataStore, 45 | * | eventEmitter, 46 | * | orderVault, 47 | * | referralStorage, 48 | * | account, 49 | * | params 50 | | ); 51 | | } 52 | | 53 | | /** 54 | | * @dev Updates the given order with the specified size delta, acceptable price, and trigger price. 55 | | * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner 56 | | * of the order, and the order must not be a market order. The size delta, trigger price, and 57 | | * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is 58 | | * transferred to the contract is added to the order's execution fee. The updated order is then saved 59 | | * in the order store, and an `OrderUpdated` event is emitted. 60 | | * 61 | | * A user may be able to observe exchange prices and prevent order execution by updating the order's 62 | | * trigger price or acceptable price 63 | | * 64 | | * The main front-running concern is if a user knows whether the price is going to move up or down 65 | | * then positions accordingly, e.g. if price is going to move up then the user opens a long position 66 | | * 67 | | * With updating of orders, a user may know that price could be lower and delays the execution of an 68 | | * order by updating it, this should not be a significant front-running concern since it is similar 69 | | * to observing prices then creating a market order as price is decreasing 70 | | * 71 | | * @param key The unique ID of the order to be updated 72 | | * @param sizeDeltaUsd The new size delta for the order 73 | | * @param acceptablePrice The new acceptable price for the order 74 | | * @param triggerPrice The new trigger price for the order 75 | | */ 76 | | function updateOrder( 77 | | bytes32 key, 78 | | uint256 sizeDeltaUsd, 79 | | uint256 acceptablePrice, 80 | | uint256 triggerPrice, 81 | | uint256 minOutputAmount, 82 | | bool autoCancel, 83 | | Order.Props memory order 84 | | ) external override globalNonReentrant onlyController { 85 | | FeatureUtils.validateFeature(dataStore, Keys.updateOrderFeatureDisabledKey(address(this), uint256(order.orderType()))); 86 | | 87 | | if (BaseOrderUtils.isMarketOrder(order.orderType())) { 88 | | revert Errors.OrderNotUpdatable(uint256(order.orderType())); 89 | | } 90 | | 91 | | order.setSizeDeltaUsd(sizeDeltaUsd); 92 | | order.setTriggerPrice(triggerPrice); 93 | | order.setAcceptablePrice(acceptablePrice); 94 | | order.setMinOutputAmount(minOutputAmount); 95 | | order.setIsFrozen(false); 96 | | order.setAutoCancel(autoCancel); 97 | | 98 | | // allow topping up of executionFee as frozen orders 99 | | // will have their executionFee reduced 100 | | address wnt = TokenUtils.wnt(dataStore); 101 | | uint256 receivedWnt = orderVault.recordTransferIn(wnt); 102 | | order.setExecutionFee(order.executionFee() + receivedWnt); 103 | | 104 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order); 105 | | uint256 oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(order.swapPath().length); 106 | | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, order.executionFee(), oraclePriceCount); 107 | | 108 | | order.touch(); 109 | | 110 | | BaseOrderUtils.validateNonEmptyOrder(order); 111 | | 112 | | OrderStoreUtils.set(dataStore, key, order); 113 | | 114 | | OrderUtils.updateAutoCancelList(dataStore, key, order, autoCancel); 115 | | OrderUtils.validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order); 116 | | 117 | | OrderEventUtils.emitOrderUpdated( 118 | | eventEmitter, 119 | | key, 120 | | order.account(), 121 | | sizeDeltaUsd, 122 | | acceptablePrice, 123 | | triggerPrice, 124 | | minOutputAmount, 125 | | order.updatedAtTime() 126 | | ); 127 | | } 128 | | 129 | | /** 130 | | * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order 131 | | * type. The caller must be the owner of the order. The order is cancelled by calling the `cancelOrder()` 132 | | * function in the `OrderUtils` contract. This function also records the starting gas amount and the 133 | | * reason for cancellation, which is passed to the `cancelOrder()` function. 134 | | * 135 | | * @param key The unique ID of the order to be cancelled 136 | | */ 137 | * | function cancelOrder(bytes32 key) external override globalNonReentrant onlyController { 138 | * | uint256 startingGas = gasleft(); 139 | | 140 | * | DataStore _dataStore = dataStore; 141 | * | Order.Props memory order = OrderStoreUtils.get(_dataStore, key); 142 | | 143 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelOrderFeatureDisabledKey(address(this), uint256(order.orderType()))); 144 | | 145 | * | if (BaseOrderUtils.isMarketOrder(order.orderType())) { 146 | * | validateRequestCancellation( 147 | * | order.updatedAtTime(), 148 | | "Order" 149 | | ); 150 | | } 151 | | 152 | * | OrderUtils.cancelOrder( 153 | * | OrderUtils.CancelOrderParams( 154 | * | dataStore, 155 | * | eventEmitter, 156 | * | orderVault, 157 | * | key, 158 | * | order.account(), 159 | * | startingGas, 160 | * | true, // isExternalCall 161 | * | Keys.USER_INITIATED_CANCEL, 162 | | "" 163 | | ) 164 | | ); 165 | | } 166 | | 167 | | // @dev simulate execution of an order to check for any errors 168 | | // @param key the order key 169 | | // @param params OracleUtils.SimulatePricesParams 170 | | function simulateExecuteOrder( 171 | | bytes32 key, 172 | | OracleUtils.SimulatePricesParams memory params 173 | | ) external 174 | | override 175 | | onlyController 176 | | withSimulatedOraclePrices(params) 177 | | globalNonReentrant 178 | | { 179 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 180 | | 181 | | this._executeOrder( 182 | | key, 183 | | order, 184 | | msg.sender 185 | | ); 186 | | } 187 | | 188 | | // @dev executes an order 189 | | // @param key the key of the order to execute 190 | | // @param oracleParams OracleUtils.SetPricesParams 191 | * | function executeOrder( 192 | | bytes32 key, 193 | | OracleUtils.SetPricesParams calldata oracleParams 194 | | ) external 195 | | globalNonReentrant 196 | | onlyOrderKeeper 197 | * | withOraclePrices(oracleParams) 198 | * | { 199 | * | uint256 startingGas = gasleft(); 200 | | 201 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 202 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order); 203 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit); 204 | | 205 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas); 206 | | 207 | * | try this._executeOrder{ gas: executionGas }( 208 | * | key, 209 | * | order, 210 | * | msg.sender 211 | | ) { 212 | * | } catch (bytes memory reasonBytes) { 213 | * | _handleOrderError(key, startingGas, reasonBytes); 214 | | } 215 | | } 216 | | 217 | | // @dev executes an order 218 | | // @param key the key of the order to execute 219 | | // @param oracleParams OracleUtils.SetPricesParams 220 | | // @param keeper the keeper executing the order 221 | | // @param startingGas the starting gas 222 | * | function _executeOrder( 223 | | bytes32 key, 224 | | Order.Props memory order, 225 | | address keeper 226 | * | ) external onlySelf { 227 | * | uint256 startingGas = gasleft(); 228 | | 229 | * | BaseOrderUtils.ExecuteOrderParams memory params = _getExecuteOrderParams( 230 | * | key, 231 | * | order, 232 | * | keeper, 233 | * | startingGas, 234 | * | Order.SecondaryOrderType.None 235 | | ); 236 | | // limit swaps require frozen order keeper for execution since on creation it can fail due to output amount 237 | | // which would automatically cause the order to be frozen 238 | | // limit increase and limit / trigger decrease orders may fail due to output amount as well and become frozen 239 | | // but only if their acceptablePrice is reached 240 | * | if (params.order.isFrozen() || params.order.orderType() == Order.OrderType.LimitSwap) { 241 | * | _validateFrozenOrderKeeper(keeper); 242 | | } 243 | | 244 | * | FeatureUtils.validateFeature(params.contracts.dataStore, Keys.executeOrderFeatureDisabledKey(address(this), uint256(params.order.orderType()))); 245 | | 246 | * | ExecuteOrderUtils.executeOrder(params); 247 | | } 248 | | 249 | | // @dev handle a caught order error 250 | | // @param key the order's key 251 | | // @param startingGas the starting gas 252 | | // @param reason the error reason 253 | | // @param reasonKey the hash or the error reason 254 | * | function _handleOrderError( 255 | | bytes32 key, 256 | | uint256 startingGas, 257 | | bytes memory reasonBytes 258 | * | ) internal { 259 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes); 260 | | 261 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes); 262 | | 263 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 264 | * | bool isMarketOrder = BaseOrderUtils.isMarketOrder(order.orderType()); 265 | | 266 | * | if ( 267 | * | OracleUtils.isOracleError(errorSelector) || 268 | | // if the order is already frozen, revert with the custom error to provide more information 269 | | // on why the order cannot be executed 270 | * | order.isFrozen() || 271 | | // for market orders, the EmptyPosition error should still lead to the 272 | | // order being cancelled 273 | | // for limit, trigger orders, the EmptyPosition error should lead to the transaction 274 | | // being reverted instead 275 | | // if the position is created or increased later, the oracle prices used to fulfill the order 276 | | // must be after the position was last increased, this is validated in DecreaseOrderUtils 277 | * | (!isMarketOrder && errorSelector == Errors.EmptyPosition.selector) || 278 | * | errorSelector == Errors.EmptyOrder.selector || 279 | | // if the order execution feature is disabled, it may be possible 280 | | // for a user to cancel their orders after the feature is re-enabled 281 | | // or they may be able to execute the order at an outdated price 282 | | // depending on the order keeper 283 | | // disabling of features should be a rare occurrence, it may be 284 | | // preferrable to still execute the orders when the feature is re-enabled 285 | | // instead of cancelling / freezing the orders 286 | | // if features are not frequently disabled, the amount of front-running 287 | | // from this should not be significant 288 | | // based on this it may also be advisable to disable the cancelling of orders 289 | | // if the execution of orders is disabled 290 | * | errorSelector == Errors.DisabledFeature.selector || 291 | * | errorSelector == Errors.InvalidKeeperForFrozenOrder.selector || 292 | * | errorSelector == Errors.UnsupportedOrderType.selector || 293 | | // the transaction is reverted for InvalidOrderPrices since the oracle prices 294 | | // do not fulfill the specified trigger price 295 | * | errorSelector == Errors.InvalidOrderPrices.selector || 296 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector 297 | | ) { 298 | * | ErrorUtils.revertWithCustomError(reasonBytes); 299 | | } 300 | | 301 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 302 | | 303 | * | if ( 304 | * | isMarketOrder || 305 | * | errorSelector == Errors.InvalidPositionMarket.selector || 306 | * | errorSelector == Errors.InvalidCollateralTokenForMarket.selector || 307 | * | errorSelector == Errors.InvalidPositionSizeValues.selector 308 | | ) { 309 | * | OrderUtils.cancelOrder( 310 | * | OrderUtils.CancelOrderParams( 311 | * | dataStore, 312 | * | eventEmitter, 313 | * | orderVault, 314 | * | key, 315 | * | msg.sender, 316 | * | startingGas, 317 | * | true, // isExternalCall 318 | * | reason, 319 | * | reasonBytes 320 | | ) 321 | | ); 322 | | 323 | * | return; 324 | | } 325 | | 326 | | // freeze unfulfillable orders to prevent the order system from being gamed 327 | | // an example of gaming would be if a user creates a limit order 328 | | // with size greater than the available amount in the pool 329 | | // the user waits for their limit price to be hit, and if price 330 | | // moves in their favour after, they can deposit into the pool 331 | | // to allow the order to be executed then close the order for a profit 332 | | // 333 | | // frozen order keepers are expected to execute orders only if the 334 | | // latest prices match the trigger price 335 | | // 336 | | // a user can also call updateOrder to unfreeze an order 337 | * | OrderUtils.freezeOrder( 338 | * | dataStore, 339 | * | eventEmitter, 340 | * | orderVault, 341 | * | key, 342 | * | msg.sender, 343 | * | startingGas, 344 | * | reason, 345 | * | reasonBytes 346 | | ); 347 | | } 348 | | 349 | | // @dev validate that the keeper is a frozen order keeper 350 | | // @param keeper address of the keeper 351 | * | function _validateFrozenOrderKeeper(address keeper) internal view { 352 | * | if (!roleStore.hasRole(keeper, Role.FROZEN_ORDER_KEEPER)) { 353 | | revert Errors.InvalidKeeperForFrozenOrder(keeper); 354 | | } 355 | | } 356 | | } 357 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/ShiftHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseHandler.sol"; 6 | | import "../shift/ShiftVault.sol"; 7 | | import "../shift/Shift.sol"; 8 | | import "../shift/ShiftUtils.sol"; 9 | | import "./IShiftHandler.sol"; 10 | | 11 | * | contract ShiftHandler is IShiftHandler, BaseHandler { 12 | | using Shift for Shift.Props; 13 | | 14 | | ShiftVault public immutable shiftVault; 15 | | 16 | | constructor( 17 | | RoleStore _roleStore, 18 | | DataStore _dataStore, 19 | | EventEmitter _eventEmitter, 20 | | Oracle _oracle, 21 | | ShiftVault _shiftVault 22 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) { 23 | | shiftVault = _shiftVault; 24 | | } 25 | | 26 | | function createShift( 27 | | address account, 28 | | ShiftUtils.CreateShiftParams calldata params 29 | | ) external override globalNonReentrant onlyController returns (bytes32) { 30 | | FeatureUtils.validateFeature(dataStore, Keys.createShiftFeatureDisabledKey(address(this))); 31 | | 32 | | return ShiftUtils.createShift( 33 | | dataStore, 34 | | eventEmitter, 35 | | shiftVault, 36 | | account, 37 | | params 38 | | ); 39 | | } 40 | | 41 | | function cancelShift(bytes32 key) external override globalNonReentrant onlyController { 42 | | uint256 startingGas = gasleft(); 43 | | 44 | | DataStore _dataStore = dataStore; 45 | | Shift.Props memory shift = ShiftStoreUtils.get(_dataStore, key); 46 | | 47 | | FeatureUtils.validateFeature(_dataStore, Keys.cancelShiftFeatureDisabledKey(address(this))); 48 | | 49 | | validateRequestCancellation( 50 | | shift.updatedAtTime(), 51 | | "Shift" 52 | | ); 53 | | 54 | | ShiftUtils.cancelShift( 55 | | _dataStore, 56 | | eventEmitter, 57 | | shiftVault, 58 | | key, 59 | | shift.account(), 60 | | startingGas, 61 | | Keys.USER_INITIATED_CANCEL, 62 | | "" 63 | | ); 64 | | } 65 | | 66 | | function executeShift( 67 | | bytes32 key, 68 | | OracleUtils.SetPricesParams calldata oracleParams 69 | | ) external 70 | | globalNonReentrant 71 | | onlyOrderKeeper 72 | | withOraclePrices(oracleParams) 73 | | { 74 | | uint256 startingGas = gasleft(); 75 | | 76 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key); 77 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift); 78 | | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit); 79 | | 80 | | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas); 81 | | 82 | | try this._executeShift{ gas: executionGas }( 83 | | key, 84 | | shift, 85 | | msg.sender 86 | | ) { 87 | | } catch (bytes memory reasonBytes) { 88 | | _handleShiftError( 89 | | key, 90 | | startingGas, 91 | | reasonBytes 92 | | ); 93 | | } 94 | | } 95 | | 96 | | function simulateExecuteShift( 97 | | bytes32 key, 98 | | OracleUtils.SimulatePricesParams memory params 99 | | ) external 100 | | override 101 | | onlyController 102 | | withSimulatedOraclePrices(params) 103 | | globalNonReentrant 104 | | { 105 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key); 106 | | 107 | | this._executeShift( 108 | | key, 109 | | shift, 110 | | msg.sender 111 | | ); 112 | | } 113 | | 114 | | function _executeShift( 115 | | bytes32 key, 116 | | Shift.Props memory shift, 117 | | address keeper 118 | | ) external onlySelf { 119 | | uint256 startingGas = gasleft(); 120 | | 121 | | FeatureUtils.validateFeature(dataStore, Keys.executeShiftFeatureDisabledKey(address(this))); 122 | | 123 | | ShiftUtils.ExecuteShiftParams memory params = ShiftUtils.ExecuteShiftParams( 124 | | dataStore, 125 | | eventEmitter, 126 | | shiftVault, 127 | | oracle, 128 | | key, 129 | | keeper, 130 | | startingGas 131 | | ); 132 | | 133 | | ShiftUtils.executeShift(params, shift); 134 | | } 135 | | 136 | | function _handleShiftError( 137 | | bytes32 key, 138 | | uint256 startingGas, 139 | | bytes memory reasonBytes 140 | | ) internal { 141 | | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes); 142 | | 143 | | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes); 144 | | 145 | | if ( 146 | | OracleUtils.isOracleError(errorSelector) || 147 | | errorSelector == Errors.DisabledFeature.selector 148 | | ) { 149 | | ErrorUtils.revertWithCustomError(reasonBytes); 150 | | } 151 | | 152 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 153 | | 154 | | ShiftUtils.cancelShift( 155 | | dataStore, 156 | | eventEmitter, 157 | | shiftVault, 158 | | key, 159 | | msg.sender, 160 | | startingGas, 161 | | reason, 162 | | reasonBytes 163 | | ); 164 | | } 165 | | } 166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/exchange/WithdrawalHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseHandler.sol"; 6 | | import "../error/ErrorUtils.sol"; 7 | | 8 | | import "../market/Market.sol"; 9 | | import "../market/MarketToken.sol"; 10 | | 11 | | import "../withdrawal/Withdrawal.sol"; 12 | | import "../withdrawal/WithdrawalVault.sol"; 13 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 14 | | import "../withdrawal/WithdrawalUtils.sol"; 15 | | import "../withdrawal/ExecuteWithdrawalUtils.sol"; 16 | | 17 | | import "./IWithdrawalHandler.sol"; 18 | | 19 | | // @title WithdrawalHandler 20 | | // @dev Contract to handle creation, execution and cancellation of withdrawals 21 | * | contract WithdrawalHandler is IWithdrawalHandler, BaseHandler { 22 | | using Withdrawal for Withdrawal.Props; 23 | | 24 | | WithdrawalVault public immutable withdrawalVault; 25 | | 26 | | constructor( 27 | | RoleStore _roleStore, 28 | | DataStore _dataStore, 29 | | EventEmitter _eventEmitter, 30 | | Oracle _oracle, 31 | | WithdrawalVault _withdrawalVault 32 | | ) BaseHandler(_roleStore, _dataStore, _eventEmitter, _oracle) { 33 | | withdrawalVault = _withdrawalVault; 34 | | } 35 | | 36 | | // @dev creates a withdrawal in the withdrawal store 37 | | // @param account the withdrawing account 38 | | // @param params WithdrawalUtils.CreateWithdrawalParams 39 | * | function createWithdrawal( 40 | | address account, 41 | | WithdrawalUtils.CreateWithdrawalParams calldata params 42 | * | ) external override globalNonReentrant onlyController returns (bytes32) { 43 | * | FeatureUtils.validateFeature(dataStore, Keys.createWithdrawalFeatureDisabledKey(address(this))); 44 | | 45 | * | return WithdrawalUtils.createWithdrawal( 46 | * | dataStore, 47 | * | eventEmitter, 48 | * | withdrawalVault, 49 | * | account, 50 | * | params 51 | | ); 52 | | } 53 | | 54 | | // @dev cancels a withdrawal 55 | | // @param key the withdrawal key 56 | * | function cancelWithdrawal(bytes32 key) external override globalNonReentrant onlyController { 57 | * | uint256 startingGas = gasleft(); 58 | | 59 | * | DataStore _dataStore = dataStore; 60 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(_dataStore, key); 61 | | 62 | * | FeatureUtils.validateFeature(_dataStore, Keys.cancelWithdrawalFeatureDisabledKey(address(this))); 63 | | 64 | * | validateRequestCancellation( 65 | * | withdrawal.updatedAtTime(), 66 | | "Withdrawal" 67 | | ); 68 | | 69 | * | WithdrawalUtils.cancelWithdrawal( 70 | * | _dataStore, 71 | * | eventEmitter, 72 | * | withdrawalVault, 73 | * | key, 74 | * | withdrawal.account(), 75 | * | startingGas, 76 | * | Keys.USER_INITIATED_CANCEL, 77 | | "" 78 | | ); 79 | | } 80 | | 81 | | // @dev executes a withdrawal 82 | | // @param key the key of the withdrawal to execute 83 | | // @param oracleParams OracleUtils.SetPricesParams 84 | * | function executeWithdrawal( 85 | | bytes32 key, 86 | | OracleUtils.SetPricesParams calldata oracleParams 87 | | ) 88 | | external 89 | | globalNonReentrant 90 | | onlyOrderKeeper 91 | * | withOraclePrices(oracleParams) 92 | * | { 93 | * | uint256 startingGas = gasleft(); 94 | | 95 | * | oracle.validateSequencerUp(); 96 | | 97 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key); 98 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal); 99 | * | GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit); 100 | | 101 | * | uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas); 102 | | 103 | * | try this._executeWithdrawal{ gas: executionGas }( 104 | * | key, 105 | * | withdrawal, 106 | * | msg.sender, 107 | * | ISwapPricingUtils.SwapPricingType.TwoStep 108 | | ) { 109 | | } catch (bytes memory reasonBytes) { 110 | * | _handleWithdrawalError( 111 | * | key, 112 | * | startingGas, 113 | * | reasonBytes 114 | | ); 115 | | } 116 | | } 117 | | 118 | | // @notice this function can only be called for markets where Chainlink 119 | | // on-chain feeds are configured for all the tokens of the market 120 | | // for example, if the market has index token as DOGE, long token as WETH 121 | | // and short token as USDC, Chainlink on-chain feeds must be configured 122 | | // for DOGE, WETH, USDC for this method to be callable for the market 123 | * | function executeAtomicWithdrawal( 124 | | address account, 125 | | WithdrawalUtils.CreateWithdrawalParams calldata params, 126 | | OracleUtils.SetPricesParams calldata oracleParams 127 | | ) 128 | | external 129 | | globalNonReentrant 130 | | onlyController 131 | * | withOraclePricesForAtomicAction(oracleParams) 132 | | { 133 | * | FeatureUtils.validateFeature(dataStore, Keys.executeAtomicWithdrawalFeatureDisabledKey(address(this))); 134 | | 135 | * | oracle.validateSequencerUp(); 136 | | 137 | * | if ( 138 | * | params.longTokenSwapPath.length != 0 || 139 | | params.shortTokenSwapPath.length != 0 140 | | ) { 141 | * | revert Errors.SwapsNotAllowedForAtomicWithdrawal( 142 | * | params.longTokenSwapPath.length, 143 | * | params.shortTokenSwapPath.length 144 | | ); 145 | | } 146 | | 147 | | bytes32 key = WithdrawalUtils.createWithdrawal( 148 | | dataStore, 149 | | eventEmitter, 150 | | withdrawalVault, 151 | | account, 152 | | params 153 | | ); 154 | | 155 | | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key); 156 | | 157 | | this._executeWithdrawal( 158 | | key, 159 | | withdrawal, 160 | | account, 161 | | ISwapPricingUtils.SwapPricingType.Atomic 162 | | ); 163 | | } 164 | | 165 | | // @dev simulate execution of a withdrawal to check for any errors 166 | | // @param key the withdrawal key 167 | | // @param params OracleUtils.SimulatePricesParams 168 | | function simulateExecuteWithdrawal( 169 | | bytes32 key, 170 | | OracleUtils.SimulatePricesParams memory params, 171 | | ISwapPricingUtils.SwapPricingType swapPricingType 172 | | ) external 173 | | override 174 | | onlyController 175 | | withSimulatedOraclePrices(params) 176 | | globalNonReentrant 177 | | { 178 | | oracle.validateSequencerUp(); 179 | | 180 | | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key); 181 | | 182 | | this._executeWithdrawal( 183 | | key, 184 | | withdrawal, 185 | | msg.sender, 186 | | swapPricingType 187 | | ); 188 | | } 189 | | 190 | | // @dev executes a withdrawal 191 | | // @param oracleParams OracleUtils.SetPricesParams 192 | | // @param keeper the keeper executing the withdrawal 193 | | // @param startingGas the starting gas 194 | * | function _executeWithdrawal( 195 | | bytes32 key, 196 | | Withdrawal.Props memory withdrawal, 197 | | address keeper, 198 | | ISwapPricingUtils.SwapPricingType swapPricingType 199 | * | ) external onlySelf { 200 | * | uint256 startingGas = gasleft(); 201 | | 202 | * | FeatureUtils.validateFeature(dataStore, Keys.executeWithdrawalFeatureDisabledKey(address(this))); 203 | | 204 | * | ExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params = ExecuteWithdrawalUtils.ExecuteWithdrawalParams( 205 | * | dataStore, 206 | * | eventEmitter, 207 | * | withdrawalVault, 208 | * | oracle, 209 | * | key, 210 | * | keeper, 211 | * | startingGas, 212 | * | swapPricingType 213 | | ); 214 | | 215 | * | ExecuteWithdrawalUtils.executeWithdrawal(params, withdrawal); 216 | | } 217 | | 218 | * | function _handleWithdrawalError( 219 | | bytes32 key, 220 | | uint256 startingGas, 221 | | bytes memory reasonBytes 222 | | ) internal { 223 | * | GasUtils.validateExecutionErrorGas(dataStore, reasonBytes); 224 | | 225 | * | bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes); 226 | | 227 | * | if ( 228 | * | OracleUtils.isOracleError(errorSelector) || 229 | * | errorSelector == Errors.DisabledFeature.selector || 230 | * | errorSelector == Errors.InsufficientGasLeftForCallback.selector 231 | | ) { 232 | | 233 | * | ErrorUtils.revertWithCustomError(reasonBytes); 234 | | } 235 | | 236 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 237 | | 238 | * | WithdrawalUtils.cancelWithdrawal( 239 | * | dataStore, 240 | * | eventEmitter, 241 | * | withdrawalVault, 242 | * | key, 243 | * | msg.sender, 244 | * | startingGas, 245 | * | reason, 246 | * | reasonBytes 247 | | ); 248 | | } 249 | | } 250 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/external/ExternalHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/Address.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 7 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 8 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 9 | | 10 | | import "./IExternalHandler.sol"; 11 | | import "../error/Errors.sol"; 12 | | 13 | | // contracts with a CONTROLLER role or other roles may need to call external 14 | | // contracts, since these roles may be able to directly change DataStore values 15 | | // or perform other sensitive operations, these contracts should make these calls 16 | | // through ExternalHandler instead 17 | | // 18 | | // note that anyone can make this contract call any function, this should be noted 19 | | // to avoid assumptions of the contract's state in any protocol 20 | | // 21 | | // e.g. some tokens require the approved amount to be zero before the approved amount 22 | | // can be changed, this should be taken into account if calling approve is required for 23 | | // these tokens 24 | * | contract ExternalHandler is IExternalHandler, ReentrancyGuard { 25 | | using Address for address; 26 | | using SafeERC20 for IERC20; 27 | | 28 | | // @notice refundTokens should be unique, this is because the refund loop 29 | | // sends the full refund token balance on each iteration, so if there are 30 | | // duplicate refund token addresses, then only the first refundReceiver 31 | | // for that token would receive the tokens 32 | | function makeExternalCalls( 33 | | address[] memory targets, 34 | | bytes[] memory dataList, 35 | | address[] memory refundTokens, 36 | | address[] memory refundReceivers 37 | | ) external nonReentrant { 38 | | if (targets.length != dataList.length) { 39 | | revert Errors.InvalidExternalCallInput(targets.length, dataList.length); 40 | | } 41 | | 42 | | if (refundTokens.length != refundReceivers.length) { 43 | | revert Errors.InvalidExternalReceiversInput(refundTokens.length, refundReceivers.length); 44 | | } 45 | | 46 | | for (uint256 i; i < targets.length; i++) { 47 | | _makeExternalCall( 48 | | targets[i], 49 | | dataList[i] 50 | | ); 51 | | } 52 | | 53 | | for (uint256 i; i < refundTokens.length; i++) { 54 | | IERC20 refundToken = IERC20(refundTokens[i]); 55 | | uint256 balance = refundToken.balanceOf(address(this)); 56 | | if (balance > 0) { 57 | | refundToken.safeTransfer(refundReceivers[i], balance); 58 | | } 59 | | } 60 | | } 61 | | 62 | | function _makeExternalCall( 63 | | address target, 64 | | bytes memory data 65 | | ) internal { 66 | | if (!target.isContract()) { 67 | | revert Errors.InvalidExternalCallTarget(target); 68 | | } 69 | | 70 | | (bool success, bytes memory returndata) = target.call(data); 71 | | 72 | | if (!success) { 73 | | revert Errors.ExternalCallFailed(returndata); 74 | | } 75 | | } 76 | | } 77 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/external/IExternalHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | interface IExternalHandler { 6 | | function makeExternalCalls( 7 | | address[] memory targets, 8 | | bytes[] memory dataList, 9 | | address[] memory refundTokens, 10 | | address[] memory refundReceivers 11 | | ) external; 12 | | } 13 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/feature/FeatureUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | 8 | | // @title FeatureUtils 9 | | // @dev Library to validate if a feature is enabled or disabled 10 | | // disabling a feature should only be used if it is absolutely necessary 11 | | // disabling of features could lead to unexpected effects, e.g. increasing / decreasing of orders 12 | | // could be disabled while liquidations may remain enabled 13 | | // this could also occur if the chain is not producing blocks and lead to liquidatable positions 14 | | // when block production resumes 15 | | // the effects of disabling features should be carefully considered 16 | * | library FeatureUtils { 17 | | // @dev get whether a feature is disabled 18 | | // @param dataStore DataStore 19 | | // @param key the feature key 20 | | // @return whether the feature is disabled 21 | * | function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) { 22 | * | return dataStore.getBool(key); 23 | | } 24 | | 25 | | // @dev validate whether a feature is enabled, reverts if the feature is disabled 26 | | // @param dataStore DataStore 27 | | // @param key the feature key 28 | * | function validateFeature(DataStore dataStore, bytes32 key) internal view { 29 | * | if (isFeatureDisabled(dataStore, key)) { 30 | | revert Errors.DisabledFeature(key); 31 | | } 32 | | } 33 | | } 34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeBatch.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title FeeBatch 6 | | // @dev Struct for fee batches 7 | * | library FeeBatch { 8 | | struct Props { 9 | | address[] feeTokens; 10 | | uint256[] feeAmounts; 11 | | uint256[] remainingAmounts; 12 | | uint256 createdAt; 13 | | } 14 | | } 15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeBatchStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./FeeBatch.sol"; 9 | | 10 | | /** 11 | | * @title FeeBatchStoreUtils 12 | | * @dev Library for fee batch storage functions 13 | | */ 14 | * | library FeeBatchStoreUtils { 15 | | using FeeBatch for FeeBatch.Props; 16 | | 17 | | bytes32 internal constant FEE_TOKENS = keccak256(abi.encode("FEE_TOKENS")); 18 | | bytes32 internal constant FEE_AMOUNTS = keccak256(abi.encode("FEE_AMOUNTS")); 19 | | bytes32 internal constant REMAINING_AMOUNTS = keccak256(abi.encode("REMAINING_AMOUNTS")); 20 | | bytes32 internal constant CREATED_AT = keccak256(abi.encode("CREATED_AT")); 21 | | 22 | | function get(DataStore dataStore, bytes32 key) internal view returns (FeeBatch.Props memory) { 23 | | FeeBatch.Props memory feeBatch; 24 | | if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) { 25 | | return feeBatch; 26 | | } 27 | | 28 | | feeBatch.feeTokens = dataStore.getAddressArray( 29 | | keccak256(abi.encode(key, FEE_TOKENS)) 30 | | ); 31 | | 32 | | feeBatch.feeAmounts = dataStore.getUintArray( 33 | | keccak256(abi.encode(key, FEE_AMOUNTS)) 34 | | ); 35 | | 36 | | feeBatch.remainingAmounts = dataStore.getUintArray( 37 | | keccak256(abi.encode(key, REMAINING_AMOUNTS)) 38 | | ); 39 | | 40 | | feeBatch.createdAt = dataStore.getUint( 41 | | keccak256(abi.encode(key, CREATED_AT)) 42 | | ); 43 | | 44 | | return feeBatch; 45 | | } 46 | | 47 | | function set(DataStore dataStore, bytes32 key, FeeBatch.Props memory feeBatch) internal { 48 | | dataStore.addBytes32( 49 | | Keys.FEE_BATCH_LIST, 50 | | key 51 | | ); 52 | | 53 | | dataStore.setAddressArray( 54 | | keccak256(abi.encode(key, FEE_TOKENS)), 55 | | feeBatch.feeTokens 56 | | ); 57 | | 58 | | dataStore.setUintArray( 59 | | keccak256(abi.encode(key, FEE_AMOUNTS)), 60 | | feeBatch.feeAmounts 61 | | ); 62 | | 63 | | dataStore.setUintArray( 64 | | keccak256(abi.encode(key, REMAINING_AMOUNTS)), 65 | | feeBatch.remainingAmounts 66 | | ); 67 | | 68 | | dataStore.setUint( 69 | | keccak256(abi.encode(key, CREATED_AT)), 70 | | feeBatch.createdAt 71 | | ); 72 | | } 73 | | 74 | | function remove(DataStore dataStore, bytes32 key) internal { 75 | | if (!dataStore.containsBytes32(Keys.FEE_BATCH_LIST, key)) { 76 | | revert Errors.FeeBatchNotFound(key); 77 | | } 78 | | 79 | | dataStore.removeBytes32( 80 | | Keys.FEE_BATCH_LIST, 81 | | key 82 | | ); 83 | | 84 | | dataStore.removeAddressArray( 85 | | keccak256(abi.encode(key, FEE_TOKENS)) 86 | | ); 87 | | 88 | | dataStore.removeUintArray( 89 | | keccak256(abi.encode(key, FEE_AMOUNTS)) 90 | | ); 91 | | 92 | | dataStore.removeUintArray( 93 | | keccak256(abi.encode(key, REMAINING_AMOUNTS)) 94 | | ); 95 | | 96 | | dataStore.removeUint( 97 | | keccak256(abi.encode(key, CREATED_AT)) 98 | | ); 99 | | } 100 | | 101 | | function getFeeBatchCount(DataStore dataStore) internal view returns (uint256) { 102 | | return dataStore.getAddressCount(Keys.FEE_BATCH_LIST); 103 | | } 104 | | 105 | | function getFeeBatchKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 106 | | return dataStore.getBytes32ValuesAt(Keys.FEE_BATCH_LIST, start, end); 107 | | } 108 | | } 109 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../role/RoleModule.sol"; 9 | | import "../fee/FeeUtils.sol"; 10 | | 11 | | // @title FeeHandler 12 | * | contract FeeHandler is ReentrancyGuard, RoleModule { 13 | | DataStore public immutable dataStore; 14 | | EventEmitter public immutable eventEmitter; 15 | | 16 | | constructor( 17 | | RoleStore _roleStore, 18 | | DataStore _dataStore, 19 | | EventEmitter _eventEmitter 20 | | ) RoleModule(_roleStore) { 21 | | dataStore = _dataStore; 22 | | eventEmitter = _eventEmitter; 23 | | } 24 | | 25 | | // @dev claim fees from the specified markets 26 | | // @param markets the markets to claim fees from 27 | | // @param tokens the fee tokens to claim 28 | | function claimFees( 29 | | address[] memory markets, 30 | | address[] memory tokens 31 | | ) external nonReentrant onlyFeeKeeper { 32 | | if (markets.length != tokens.length) { 33 | | revert Errors.InvalidClaimFeesInput(markets.length, tokens.length); 34 | | } 35 | | 36 | | address receiver = dataStore.getAddress(Keys.FEE_RECEIVER); 37 | | 38 | | for (uint256 i; i < markets.length; i++) { 39 | | FeeUtils.claimFees( 40 | | dataStore, 41 | | eventEmitter, 42 | | markets[i], 43 | | tokens[i], 44 | | receiver 45 | | ); 46 | | } 47 | | } 48 | | } 49 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeSwapUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../v1/IVaultV1.sol"; 6 | | import "../v1/IRouterV1.sol"; 7 | | 8 | | import "../data/DataStore.sol"; 9 | | import "../role/RoleModule.sol"; 10 | | import "../fee/FeeUtils.sol"; 11 | | import "../fee/FeeBatchStoreUtils.sol"; 12 | | import "../market/Market.sol"; 13 | | import "../nonce/NonceUtils.sol"; 14 | | import "../router/IExchangeRouter.sol"; 15 | | 16 | | // @title FeeSwapUtils 17 | * | library FeeSwapUtils { 18 | | function swapFeesUsingV1( 19 | | DataStore dataStore, 20 | | IRouterV1 routerV1, 21 | | address bridgingToken, 22 | | bytes32 feeBatchKey, 23 | | uint256 tokenIndex, 24 | | address[] memory path, 25 | | uint256 swapAmount, 26 | | uint256 minOut 27 | | ) internal { 28 | | (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues( 29 | | dataStore, 30 | | feeBatchKey, 31 | | tokenIndex, 32 | | swapAmount 33 | | ); 34 | | 35 | | if (path[path.length - 1] != bridgingToken) { 36 | | revert Errors.InvalidSwapPathForV1(path, bridgingToken); 37 | | } 38 | | 39 | | feeBatch.remainingAmounts[tokenIndex] -= swapAmount; 40 | | FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch); 41 | | 42 | | IERC20(tokenIn).approve(address(routerV1), swapAmount); 43 | | routerV1.swap(path, swapAmount, minOut, address(this)); 44 | | } 45 | | 46 | | function swapFeesUsingV2( 47 | | DataStore dataStore, 48 | | address routerV2, 49 | | IExchangeRouter exchangeRouterV2, 50 | | address bridgingToken, 51 | | bytes32 feeBatchKey, 52 | | uint256 tokenIndex, 53 | | address market, 54 | | address[] memory swapPath, 55 | | uint256 swapAmount, 56 | | uint256 executionFee, 57 | | uint256 minOut 58 | | ) internal { 59 | | (FeeBatch.Props memory feeBatch, address tokenIn) = _getSwapValues( 60 | | dataStore, 61 | | feeBatchKey, 62 | | tokenIndex, 63 | | swapAmount 64 | | ); 65 | | 66 | | SwapUtils.validateSwapOutputToken(dataStore, swapPath, tokenIn, bridgingToken); 67 | | 68 | | IBaseOrderUtils.CreateOrderParams memory params = _getSwapOrderParamsV2( 69 | | dataStore, 70 | | market, 71 | | tokenIn, 72 | | swapPath, 73 | | swapAmount, 74 | | executionFee, 75 | | minOut 76 | | ); 77 | | 78 | | feeBatch.remainingAmounts[tokenIndex] -= swapAmount; 79 | | FeeBatchStoreUtils.set(dataStore, feeBatchKey, feeBatch); 80 | | 81 | | IERC20(tokenIn).approve(routerV2, swapAmount); 82 | | bytes32 orderKey = exchangeRouterV2.createOrder{ value: msg.value }(params); 83 | | dataStore.setBytes32(Keys.feeDistributorSwapFeeBatchKey(orderKey), feeBatchKey); 84 | | dataStore.setUint(Keys.feeDistributorSwapTokenIndexKey(orderKey), tokenIndex); 85 | | } 86 | | 87 | | function _getSwapValues( 88 | | DataStore dataStore, 89 | | bytes32 feeBatchKey, 90 | | uint256 tokenIndex, 91 | | uint256 swapAmount 92 | | ) internal view returns (FeeBatch.Props memory, address) { 93 | | FeeBatch.Props memory feeBatch = FeeBatchStoreUtils.get(dataStore, feeBatchKey); 94 | | 95 | | if (tokenIndex > feeBatch.feeTokens.length) { 96 | | revert Errors.InvalidFeeBatchTokenIndex(tokenIndex, feeBatch.feeTokens.length); 97 | | } 98 | | 99 | | address tokenIn = feeBatch.feeTokens[tokenIndex]; 100 | | uint256 remainingAmount = feeBatch.remainingAmounts[tokenIndex]; 101 | | if (swapAmount > remainingAmount) { 102 | | revert Errors.InvalidAmountInForFeeBatch(swapAmount, remainingAmount); 103 | | } 104 | | 105 | | return (feeBatch, tokenIn); 106 | | } 107 | | 108 | | function _getSwapOrderParamsV2( 109 | | DataStore dataStore, 110 | | address market, 111 | | address tokenIn, 112 | | address[] memory swapPath, 113 | | uint256 swapAmount, 114 | | uint256 executionFee, 115 | | uint256 minOut 116 | | ) internal view returns (IBaseOrderUtils.CreateOrderParams memory) { 117 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses = IBaseOrderUtils.CreateOrderParamsAddresses( 118 | | address(this), // receiver 119 | | address(this), // cancellationReceiver 120 | | address(this), // callbackContract 121 | | address(0), // uiFeeReceiver 122 | | market, // market 123 | | tokenIn, // initialCollateralToken 124 | | swapPath // swapPath 125 | | ); 126 | | 127 | | uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT); 128 | | 129 | | IBaseOrderUtils.CreateOrderParamsNumbers memory numbers = IBaseOrderUtils.CreateOrderParamsNumbers( 130 | | 0, // sizeDeltaUsd 131 | | swapAmount, // initialCollateralDeltaAmount 132 | | 0, // triggerPrice 133 | | 0, // acceptablePrice 134 | | executionFee, // executionFee 135 | | maxCallbackGasLimit, // callbackGasLimit 136 | | minOut // minOutputAmount 137 | | ); 138 | | 139 | | IBaseOrderUtils.CreateOrderParams memory params = IBaseOrderUtils.CreateOrderParams( 140 | | addresses, // addresses 141 | | numbers, // numbers 142 | | Order.OrderType.MarketSwap, // orderType 143 | | Order.DecreasePositionSwapType.NoSwap, // decreasePositionSwapType 144 | | false, // isLong 145 | | false, // shouldUnwrapNativeToken 146 | | false, // autoCancel 147 | | bytes32(0) // referralCode 148 | | ); 149 | | 150 | | return params; 151 | | } 152 | | } 153 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/fee/FeeUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | 8 | | import "../event/EventEmitter.sol"; 9 | | import "../event/EventUtils.sol"; 10 | | import "../utils/Cast.sol"; 11 | | import "../utils/AccountUtils.sol"; 12 | | import "../market/MarketUtils.sol"; 13 | | 14 | | import "../market/MarketToken.sol"; 15 | | 16 | | // @title FeeUtils 17 | | // @dev Library for fee actions 18 | * | library FeeUtils { 19 | | using EventUtils for EventUtils.AddressItems; 20 | | using EventUtils for EventUtils.UintItems; 21 | | using EventUtils for EventUtils.IntItems; 22 | | using EventUtils for EventUtils.BoolItems; 23 | | using EventUtils for EventUtils.Bytes32Items; 24 | | using EventUtils for EventUtils.BytesItems; 25 | | using EventUtils for EventUtils.StringItems; 26 | | 27 | | // @dev increment the claimable fee amount 28 | | // @param dataStore DataStore 29 | | // @param eventEmitter EventEmitter 30 | | // @param market the market to increment claimable fees for 31 | | // @param token the fee token 32 | | // @param delta the amount to increment 33 | | // @param feeType the type of the fee 34 | * | function incrementClaimableFeeAmount( 35 | | DataStore dataStore, 36 | | EventEmitter eventEmitter, 37 | | address market, 38 | | address token, 39 | | uint256 delta, 40 | | bytes32 feeType 41 | * | ) internal { 42 | * | if (delta == 0) { 43 | * | return; 44 | | } 45 | | 46 | * | bytes32 key = Keys.claimableFeeAmountKey(market, token); 47 | | 48 | * | uint256 nextValue = dataStore.incrementUint( 49 | * | key, 50 | * | delta 51 | | ); 52 | | 53 | * | emitClaimableFeeAmountUpdated( 54 | * | eventEmitter, 55 | * | market, 56 | * | token, 57 | * | delta, 58 | * | nextValue, 59 | * | feeType 60 | | ); 61 | | } 62 | | 63 | * | function incrementClaimableUiFeeAmount( 64 | | DataStore dataStore, 65 | | EventEmitter eventEmitter, 66 | | address uiFeeReceiver, 67 | | address market, 68 | | address token, 69 | | uint256 delta, 70 | | bytes32 feeType 71 | | ) internal { 72 | * | if (delta == 0) { 73 | * | return; 74 | | } 75 | | 76 | | uint256 nextValue = dataStore.incrementUint( 77 | | Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver), 78 | | delta 79 | | ); 80 | | 81 | | uint256 nextPoolValue = dataStore.incrementUint( 82 | | Keys.claimableUiFeeAmountKey(market, token), 83 | | delta 84 | | ); 85 | | 86 | | emitClaimableUiFeeAmountUpdated( 87 | | eventEmitter, 88 | | uiFeeReceiver, 89 | | market, 90 | | token, 91 | | delta, 92 | | nextValue, 93 | | nextPoolValue, 94 | | feeType 95 | | ); 96 | | } 97 | | 98 | | // @dev claim fees for the specified market 99 | | // @param dataStore DataStore 100 | | // @param eventEmitter EventEmitter 101 | | // @param market the market to claim fees for 102 | | // @param token the fee token 103 | | // @param receiver the receiver of the claimed fees 104 | | function claimFees( 105 | | DataStore dataStore, 106 | | EventEmitter eventEmitter, 107 | | address market, 108 | | address token, 109 | | address receiver 110 | | ) internal returns (uint256) { 111 | | AccountUtils.validateReceiver(receiver); 112 | | 113 | | bytes32 key = Keys.claimableFeeAmountKey(market, token); 114 | | 115 | | uint256 feeAmount = dataStore.getUint(key); 116 | | dataStore.setUint(key, 0); 117 | | 118 | | MarketToken(payable(market)).transferOut( 119 | | token, 120 | | receiver, 121 | | feeAmount 122 | | ); 123 | | 124 | | MarketUtils.validateMarketTokenBalance(dataStore, market); 125 | | 126 | | emitFeesClaimed( 127 | | eventEmitter, 128 | | market, 129 | | receiver, 130 | | feeAmount 131 | | ); 132 | | 133 | | return feeAmount; 134 | | } 135 | | 136 | | function claimUiFees( 137 | | DataStore dataStore, 138 | | EventEmitter eventEmitter, 139 | | address uiFeeReceiver, 140 | | address market, 141 | | address token, 142 | | address receiver 143 | | ) internal returns (uint256) { 144 | | AccountUtils.validateReceiver(receiver); 145 | | 146 | | bytes32 key = Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver); 147 | | 148 | | uint256 feeAmount = dataStore.getUint(key); 149 | | dataStore.setUint(key, 0); 150 | | 151 | | uint256 nextPoolValue = dataStore.decrementUint( 152 | | Keys.claimableUiFeeAmountKey(market, token), 153 | | feeAmount 154 | | ); 155 | | 156 | | MarketToken(payable(market)).transferOut( 157 | | token, 158 | | receiver, 159 | | feeAmount 160 | | ); 161 | | 162 | | MarketUtils.validateMarketTokenBalance(dataStore, market); 163 | | 164 | | emitUiFeesClaimed( 165 | | eventEmitter, 166 | | uiFeeReceiver, 167 | | market, 168 | | receiver, 169 | | feeAmount, 170 | | nextPoolValue 171 | | ); 172 | | 173 | | return feeAmount; 174 | | } 175 | | 176 | * | function emitClaimableFeeAmountUpdated( 177 | | EventEmitter eventEmitter, 178 | | address market, 179 | | address token, 180 | | uint256 delta, 181 | | uint256 nextValue, 182 | | bytes32 feeType 183 | * | ) internal { 184 | * | EventUtils.EventLogData memory eventData; 185 | | 186 | * | eventData.addressItems.initItems(2); 187 | * | eventData.addressItems.setItem(0, "market", market); 188 | * | eventData.addressItems.setItem(1, "token", token); 189 | | 190 | * | eventData.uintItems.initItems(2); 191 | * | eventData.uintItems.setItem(0, "delta", delta); 192 | * | eventData.uintItems.setItem(1, "nextValue", nextValue); 193 | | 194 | * | eventData.bytes32Items.initItems(1); 195 | * | eventData.bytes32Items.setItem(0, "feeType", feeType); 196 | | 197 | * | eventEmitter.emitEventLog2( 198 | | "ClaimableFeeAmountUpdated", 199 | * | Cast.toBytes32(market), 200 | * | feeType, 201 | * | eventData 202 | | ); 203 | | } 204 | | 205 | | function emitClaimableUiFeeAmountUpdated( 206 | | EventEmitter eventEmitter, 207 | | address uiFeeReceiver, 208 | | address market, 209 | | address token, 210 | | uint256 delta, 211 | | uint256 nextValue, 212 | | uint256 nextPoolValue, 213 | | bytes32 feeType 214 | | ) internal { 215 | | EventUtils.EventLogData memory eventData; 216 | | 217 | | eventData.addressItems.initItems(3); 218 | | eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver); 219 | | eventData.addressItems.setItem(1, "market", market); 220 | | eventData.addressItems.setItem(2, "token", token); 221 | | 222 | | eventData.uintItems.initItems(3); 223 | | eventData.uintItems.setItem(0, "delta", delta); 224 | | eventData.uintItems.setItem(1, "nextValue", nextValue); 225 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue); 226 | | 227 | | eventData.bytes32Items.initItems(1); 228 | | eventData.bytes32Items.setItem(0, "feeType", feeType); 229 | | 230 | | eventEmitter.emitEventLog2( 231 | | "ClaimableUiFeeAmountUpdated", 232 | | Cast.toBytes32(market), 233 | | feeType, 234 | | eventData 235 | | ); 236 | | } 237 | | 238 | | function emitFeesClaimed( 239 | | EventEmitter eventEmitter, 240 | | address market, 241 | | address receiver, 242 | | uint256 feeAmount 243 | | ) internal { 244 | | EventUtils.EventLogData memory eventData; 245 | | 246 | | eventData.addressItems.initItems(2); 247 | | eventData.addressItems.setItem(0, "market", market); 248 | | eventData.addressItems.setItem(1, "receiver", receiver); 249 | | 250 | | eventData.uintItems.initItems(1); 251 | | eventData.uintItems.setItem(0, "feeAmount", feeAmount); 252 | | 253 | | eventEmitter.emitEventLog1( 254 | | "FeesClaimed", 255 | | Cast.toBytes32(market), 256 | | eventData 257 | | ); 258 | | } 259 | | 260 | | function emitUiFeesClaimed( 261 | | EventEmitter eventEmitter, 262 | | address uiFeeReceiver, 263 | | address market, 264 | | address receiver, 265 | | uint256 feeAmount, 266 | | uint256 nextPoolValue 267 | | ) internal { 268 | | EventUtils.EventLogData memory eventData; 269 | | 270 | | eventData.addressItems.initItems(3); 271 | | eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver); 272 | | eventData.addressItems.setItem(1, "market", market); 273 | | eventData.addressItems.setItem(2, "receiver", receiver); 274 | | 275 | | eventData.uintItems.initItems(2); 276 | | eventData.uintItems.setItem(0, "feeAmount", feeAmount); 277 | | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue); 278 | | 279 | | eventEmitter.emitEventLog1( 280 | | "UiFeesClaimed", 281 | | Cast.toBytes32(market), 282 | | eventData 283 | | ); 284 | | } 285 | | } 286 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gas/GasUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../callback/CallbackUtils.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../data/Keys.sol"; 9 | | import "../utils/Precision.sol"; 10 | | 11 | | import "../deposit/Deposit.sol"; 12 | | import "../withdrawal/Withdrawal.sol"; 13 | | import "../shift/Shift.sol"; 14 | | import "../order/Order.sol"; 15 | | import "../order/BaseOrderUtils.sol"; 16 | | 17 | | import "../bank/StrictBank.sol"; 18 | | 19 | | // @title GasUtils 20 | | // @dev Library for execution fee estimation and payments 21 | * | library GasUtils { 22 | | using Deposit for Deposit.Props; 23 | | using Withdrawal for Withdrawal.Props; 24 | | using Shift for Shift.Props; 25 | | using Order for Order.Props; 26 | | using GlvDeposit for GlvDeposit.Props; 27 | | 28 | | using EventUtils for EventUtils.AddressItems; 29 | | using EventUtils for EventUtils.UintItems; 30 | | using EventUtils for EventUtils.IntItems; 31 | | using EventUtils for EventUtils.BoolItems; 32 | | using EventUtils for EventUtils.Bytes32Items; 33 | | using EventUtils for EventUtils.BytesItems; 34 | | using EventUtils for EventUtils.StringItems; 35 | | 36 | | // @param keeper address of the keeper 37 | | // @param amount the amount of execution fee received 38 | | event KeeperExecutionFee(address keeper, uint256 amount); 39 | | // @param user address of the user 40 | | // @param amount the amount of execution fee refunded 41 | | event UserRefundFee(address user, uint256 amount); 42 | | 43 | | function getMinHandleExecutionErrorGas( 44 | | DataStore dataStore 45 | | ) internal view returns (uint256) { 46 | | return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS); 47 | | } 48 | | 49 | * | function getMinHandleExecutionErrorGasToForward( 50 | | DataStore dataStore 51 | * | ) internal view returns (uint256) { 52 | * | return 53 | * | dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD); 54 | | } 55 | | 56 | * | function getMinAdditionalGasForExecution( 57 | | DataStore dataStore 58 | * | ) internal view returns (uint256) { 59 | * | return dataStore.getUint(Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION); 60 | | } 61 | | 62 | * | function getExecutionGas( 63 | | DataStore dataStore, 64 | | uint256 startingGas 65 | * | ) internal view returns (uint256) { 66 | * | uint256 minHandleExecutionErrorGasToForward = GasUtils 67 | * | .getMinHandleExecutionErrorGasToForward(dataStore); 68 | * | if (startingGas < minHandleExecutionErrorGasToForward) { 69 | | revert Errors.InsufficientExecutionGasForErrorHandling( 70 | | startingGas, 71 | | minHandleExecutionErrorGasToForward 72 | | ); 73 | | } 74 | | 75 | * | return startingGas - minHandleExecutionErrorGasToForward; 76 | | } 77 | | 78 | * | function validateExecutionGas( 79 | | DataStore dataStore, 80 | | uint256 startingGas, 81 | | uint256 estimatedGasLimit 82 | * | ) internal view { 83 | * | uint256 minAdditionalGasForExecution = getMinAdditionalGasForExecution( 84 | * | dataStore 85 | | ); 86 | * | if (startingGas < estimatedGasLimit + minAdditionalGasForExecution) { 87 | | revert Errors.InsufficientExecutionGas( 88 | | startingGas, 89 | | estimatedGasLimit, 90 | | minAdditionalGasForExecution 91 | | ); 92 | | } 93 | | } 94 | | 95 | | // a minimum amount of gas is required to be left for cancellation 96 | | // to prevent potential blocking of cancellations by malicious contracts using e.g. large revert reasons 97 | | // 98 | | // during the estimateGas call by keepers, an insufficient amount of gas may be estimated 99 | | // the amount estimated may be insufficient for execution but sufficient for cancellaton 100 | | // this could lead to invalid cancellations due to insufficient gas used by keepers 101 | | // 102 | | // to help prevent this, out of gas errors are attempted to be caught and reverted for estimateGas calls 103 | | // 104 | | // a malicious user could cause the estimateGas call of a keeper to fail, in which case the keeper could 105 | | // still attempt to execute the transaction with a reasonable gas limit 106 | * | function validateExecutionErrorGas( 107 | | DataStore dataStore, 108 | | bytes memory reasonBytes 109 | | ) internal view { 110 | | // skip the validation if the execution did not fail due to an out of gas error 111 | | // also skip the validation if this is not invoked in an estimateGas call (tx.origin != address(0)) 112 | * | if (reasonBytes.length != 0 || tx.origin != address(0)) { 113 | * | return; 114 | | } 115 | | 116 | | uint256 gas = gasleft(); 117 | | uint256 minHandleExecutionErrorGas = getMinHandleExecutionErrorGas( 118 | | dataStore 119 | | ); 120 | | 121 | | if (gas < minHandleExecutionErrorGas) { 122 | | revert Errors.InsufficientHandleExecutionErrorGas( 123 | | gas, 124 | | minHandleExecutionErrorGas 125 | | ); 126 | | } 127 | | } 128 | | 129 | | struct PayExecutionFeeCache { 130 | | uint256 refundFeeAmount; 131 | | bool refundWasSent; 132 | | } 133 | | 134 | | // @dev pay the keeper the execution fee and refund any excess amount 135 | | // 136 | | // @param dataStore DataStore 137 | | // @param bank the StrictBank contract holding the execution fee 138 | | // @param executionFee the executionFee amount 139 | | // @param startingGas the starting gas 140 | | // @param oraclePriceCount number of oracle prices 141 | | // @param keeper the keeper to pay 142 | | // @param refundReceiver the account that should receive any excess gas refunds 143 | * | function payExecutionFee( 144 | | DataStore dataStore, 145 | | EventEmitter eventEmitter, 146 | | StrictBank bank, 147 | | bytes32 key, 148 | | address callbackContract, 149 | | uint256 executionFee, 150 | | uint256 startingGas, 151 | | uint256 oraclePriceCount, 152 | | address keeper, 153 | | address refundReceiver 154 | * | ) internal { 155 | * | if (executionFee == 0) { 156 | * | return; 157 | | } 158 | | 159 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 160 | | // startingGas -= gasleft() / 63; //NOTE: foundry bug hotfix: comment out 161 | * | uint256 gasUsed = startingGas - gasleft(); 162 | | 163 | | // each internal call forwards 63/64 of the remaining gas 164 | * | uint256 executionFeeForKeeper = adjustGasUsage( 165 | * | dataStore, 166 | * | gasUsed, 167 | * | oraclePriceCount 168 | * | ) * tx.gasprice; 169 | | 170 | * | if (executionFeeForKeeper > executionFee) { 171 | * | executionFeeForKeeper = executionFee; 172 | | } 173 | | 174 | * | bank.transferOutNativeToken(keeper, executionFeeForKeeper); 175 | | 176 | * | emitKeeperExecutionFee(eventEmitter, keeper, executionFeeForKeeper); 177 | | 178 | * | PayExecutionFeeCache memory cache; 179 | | 180 | * | cache.refundFeeAmount = executionFee - executionFeeForKeeper; 181 | * | if (cache.refundFeeAmount == 0) { 182 | * | return; 183 | | } 184 | | 185 | * | address _wnt = dataStore.getAddress(Keys.WNT); 186 | * | bank.transferOut(_wnt, address(this), cache.refundFeeAmount); 187 | | 188 | * | IWNT(_wnt).withdraw(cache.refundFeeAmount); 189 | | 190 | * | EventUtils.EventLogData memory eventData; 191 | | 192 | * | cache.refundWasSent = CallbackUtils.refundExecutionFee( 193 | * | dataStore, 194 | * | key, 195 | * | callbackContract, 196 | * | cache.refundFeeAmount, 197 | * | eventData 198 | | ); 199 | | 200 | * | if (cache.refundWasSent) { 201 | * | emitExecutionFeeRefundCallback( 202 | * | eventEmitter, 203 | * | callbackContract, 204 | * | cache.refundFeeAmount 205 | | ); 206 | | } else { 207 | | TokenUtils.sendNativeToken( 208 | | dataStore, 209 | | refundReceiver, 210 | | cache.refundFeeAmount 211 | | ); 212 | | emitExecutionFeeRefund( 213 | | eventEmitter, 214 | | refundReceiver, 215 | | cache.refundFeeAmount 216 | | ); 217 | | } 218 | | } 219 | | 220 | | // @dev validate that the provided executionFee is sufficient based on the estimatedGasLimit 221 | | // @param dataStore DataStore 222 | | // @param estimatedGasLimit the estimated gas limit 223 | | // @param executionFee the execution fee provided 224 | | // @param oraclePriceCount 225 | * | function validateExecutionFee( 226 | | DataStore dataStore, 227 | | uint256 estimatedGasLimit, 228 | | uint256 executionFee, 229 | | uint256 oraclePriceCount 230 | * | ) internal view { 231 | * | uint256 gasLimit = adjustGasLimitForEstimate( 232 | * | dataStore, 233 | * | estimatedGasLimit, 234 | * | oraclePriceCount 235 | | ); 236 | * | uint256 minExecutionFee = gasLimit * tx.gasprice; 237 | * | if (executionFee < minExecutionFee) { 238 | * | revert Errors.InsufficientExecutionFee( 239 | * | minExecutionFee, 240 | * | executionFee 241 | | ); 242 | | } 243 | | } 244 | | 245 | | // @dev adjust the gas usage to pay a small amount to keepers 246 | | // @param dataStore DataStore 247 | | // @param gasUsed the amount of gas used 248 | | // @param oraclePriceCount number of oracle prices 249 | * | function adjustGasUsage( 250 | | DataStore dataStore, 251 | | uint256 gasUsed, 252 | | uint256 oraclePriceCount 253 | * | ) internal view returns (uint256) { 254 | | // gas measurements are done after the call to withOraclePrices 255 | | // withOraclePrices may consume a significant amount of gas 256 | | // the baseGasLimit used to calculate the execution cost 257 | | // should be adjusted to account for this 258 | | // additionally, a transaction could fail midway through an execution transaction 259 | | // before being cancelled, the possibility of this additional gas cost should 260 | | // be considered when setting the baseGasLimit 261 | * | uint256 baseGasLimit = dataStore.getUint( 262 | | Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 263 | | ); 264 | * | baseGasLimit += 265 | * | dataStore.getUint(Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE) * 266 | * | oraclePriceCount; 267 | | // the gas cost is estimated based on the gasprice of the request txn 268 | | // the actual cost may be higher if the gasprice is higher in the execution txn 269 | | // the multiplierFactor should be adjusted to account for this 270 | * | uint256 multiplierFactor = dataStore.getUint( 271 | | Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR 272 | | ); 273 | * | uint256 gasLimit = baseGasLimit + 274 | * | Precision.applyFactor(gasUsed, multiplierFactor); 275 | * | return gasLimit; 276 | | } 277 | | 278 | | // @dev adjust the estimated gas limit to help ensure the execution fee is sufficient during 279 | | // the actual execution 280 | | // @param dataStore DataStore 281 | | // @param estimatedGasLimit the estimated gas limit 282 | * | function adjustGasLimitForEstimate( 283 | | DataStore dataStore, 284 | | uint256 estimatedGasLimit, 285 | | uint256 oraclePriceCount 286 | * | ) internal view returns (uint256) { 287 | * | uint256 baseGasLimit = dataStore.getUint( 288 | | Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 289 | | ); 290 | * | baseGasLimit += 291 | * | dataStore.getUint(Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) * 292 | * | oraclePriceCount; 293 | * | uint256 multiplierFactor = dataStore.getUint( 294 | | Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR 295 | | ); 296 | * | uint256 gasLimit = baseGasLimit + 297 | * | Precision.applyFactor(estimatedGasLimit, multiplierFactor); 298 | * | return gasLimit; 299 | | } 300 | | 301 | | // @dev get estimated number of oracle prices for deposit 302 | | // @param swapsCount number of swaps in the deposit 303 | * | function estimateDepositOraclePriceCount( 304 | | uint256 swapsCount 305 | * | ) internal pure returns (uint256) { 306 | * | return 3 + swapsCount; 307 | | } 308 | | 309 | | // @dev get estimated number of oracle prices for withdrawal 310 | | // @param swapsCount number of swaps in the withdrawal 311 | * | function estimateWithdrawalOraclePriceCount( 312 | | uint256 swapsCount 313 | * | ) internal pure returns (uint256) { 314 | * | return 3 + swapsCount; 315 | | } 316 | | 317 | | // @dev get estimated number of oracle prices for order 318 | | // @param swapsCount number of swaps in the order 319 | * | function estimateOrderOraclePriceCount( 320 | | uint256 swapsCount 321 | * | ) internal pure returns (uint256) { 322 | * | return 3 + swapsCount; 323 | | } 324 | | 325 | | // @dev get estimated number of oracle prices for shift 326 | | function estimateShiftOraclePriceCount() internal pure returns (uint256) { 327 | | return 4; 328 | | } 329 | | 330 | | // @dev get estimated number of oracle prices for glv deposit 331 | | // @param marketCount number of markets in the glv 332 | | // @param swapsCount number of swaps in the glv deposit 333 | | function estimateGlvDepositOraclePriceCount( 334 | | uint256 marketCount, 335 | | uint256 swapsCount 336 | | ) internal pure returns (uint256) { 337 | | return 2 + marketCount + swapsCount; 338 | | } 339 | | 340 | | // @dev the estimated gas limit for deposits 341 | | // @param dataStore DataStore 342 | | // @param deposit the deposit to estimate the gas limit for 343 | * | function estimateExecuteDepositGasLimit( 344 | | DataStore dataStore, 345 | | Deposit.Props memory deposit 346 | * | ) internal view returns (uint256) { 347 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 348 | * | uint256 swapCount = deposit.longTokenSwapPath().length + 349 | * | deposit.shortTokenSwapPath().length; 350 | * | uint256 gasForSwaps = swapCount * gasPerSwap; 351 | | 352 | * | if ( 353 | * | deposit.initialLongTokenAmount() == 0 || 354 | * | deposit.initialShortTokenAmount() == 0 355 | | ) { 356 | | return 357 | | dataStore.getUint(Keys.depositGasLimitKey(true)) + 358 | | deposit.callbackGasLimit() + 359 | | gasForSwaps; 360 | | } 361 | | 362 | * | return 363 | * | dataStore.getUint(Keys.depositGasLimitKey(false)) + 364 | * | deposit.callbackGasLimit() + 365 | * | gasForSwaps; 366 | | } 367 | | 368 | | // @dev the estimated gas limit for withdrawals 369 | | // @param dataStore DataStore 370 | | // @param withdrawal the withdrawal to estimate the gas limit for 371 | * | function estimateExecuteWithdrawalGasLimit( 372 | | DataStore dataStore, 373 | | Withdrawal.Props memory withdrawal 374 | * | ) internal view returns (uint256) { 375 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 376 | * | uint256 swapCount = withdrawal.longTokenSwapPath().length + 377 | * | withdrawal.shortTokenSwapPath().length; 378 | * | uint256 gasForSwaps = swapCount * gasPerSwap; 379 | | 380 | * | return 381 | * | dataStore.getUint(Keys.withdrawalGasLimitKey()) + 382 | * | withdrawal.callbackGasLimit() + 383 | * | gasForSwaps; 384 | | } 385 | | 386 | | // @dev the estimated gas limit for shifts 387 | | // @param dataStore DataStore 388 | | // @param shift the shift to estimate the gas limit for 389 | | function estimateExecuteShiftGasLimit( 390 | | DataStore dataStore, 391 | | Shift.Props memory shift 392 | | ) internal view returns (uint256) { 393 | | return 394 | | dataStore.getUint(Keys.shiftGasLimitKey()) + 395 | | shift.callbackGasLimit(); 396 | | } 397 | | 398 | | // @dev the estimated gas limit for orders 399 | | // @param dataStore DataStore 400 | | // @param order the order to estimate the gas limit for 401 | * | function estimateExecuteOrderGasLimit( 402 | | DataStore dataStore, 403 | | Order.Props memory order 404 | * | ) internal view returns (uint256) { 405 | * | if (BaseOrderUtils.isIncreaseOrder(order.orderType())) { 406 | * | return estimateExecuteIncreaseOrderGasLimit(dataStore, order); 407 | | } 408 | | 409 | * | if (BaseOrderUtils.isDecreaseOrder(order.orderType())) { 410 | * | return estimateExecuteDecreaseOrderGasLimit(dataStore, order); 411 | | } 412 | | 413 | * | if (BaseOrderUtils.isSwapOrder(order.orderType())) { 414 | * | return estimateExecuteSwapOrderGasLimit(dataStore, order); 415 | | } 416 | | 417 | | revert Errors.UnsupportedOrderType(uint256(order.orderType())); 418 | | } 419 | | 420 | | // @dev the estimated gas limit for increase orders 421 | | // @param dataStore DataStore 422 | | // @param order the order to estimate the gas limit for 423 | * | function estimateExecuteIncreaseOrderGasLimit( 424 | | DataStore dataStore, 425 | | Order.Props memory order 426 | * | ) internal view returns (uint256) { 427 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 428 | * | return 429 | * | dataStore.getUint(Keys.increaseOrderGasLimitKey()) + 430 | * | gasPerSwap * 431 | * | order.swapPath().length + 432 | * | order.callbackGasLimit(); 433 | | } 434 | | 435 | | // @dev the estimated gas limit for decrease orders 436 | | // @param dataStore DataStore 437 | | // @param order the order to estimate the gas limit for 438 | * | function estimateExecuteDecreaseOrderGasLimit( 439 | | DataStore dataStore, 440 | | Order.Props memory order 441 | * | ) internal view returns (uint256) { 442 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 443 | * | uint256 swapCount = order.swapPath().length; 444 | * | if ( 445 | * | order.decreasePositionSwapType() != 446 | * | Order.DecreasePositionSwapType.NoSwap 447 | | ) { 448 | * | swapCount += 1; 449 | | } 450 | | 451 | * | return 452 | * | dataStore.getUint(Keys.decreaseOrderGasLimitKey()) + 453 | * | gasPerSwap * 454 | * | swapCount + 455 | * | order.callbackGasLimit(); 456 | | } 457 | | 458 | | // @dev the estimated gas limit for swap orders 459 | | // @param dataStore DataStore 460 | | // @param order the order to estimate the gas limit for 461 | * | function estimateExecuteSwapOrderGasLimit( 462 | | DataStore dataStore, 463 | | Order.Props memory order 464 | * | ) internal view returns (uint256) { 465 | * | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 466 | * | return 467 | * | dataStore.getUint(Keys.swapOrderGasLimitKey()) + 468 | * | gasPerSwap * 469 | * | order.swapPath().length + 470 | * | order.callbackGasLimit(); 471 | | } 472 | | 473 | | // @dev the estimated gas limit for glv deposits 474 | | // @param dataStore DataStore 475 | | // @param deposit the deposit to estimate the gas limit for 476 | | function estimateExecuteGlvDepositGasLimit( 477 | | DataStore dataStore, 478 | | GlvDeposit.Props memory glvDeposit, 479 | | uint256 marketCount 480 | | ) internal view returns (uint256) { 481 | | // glv deposit execution gas consumption depends on the amount of markets 482 | | uint256 gasPerGlvPerMarket = dataStore.getUint( 483 | | Keys.glvPerMarketGasLimitKey() 484 | | ); 485 | | uint256 gasForGlvMarkets = gasPerGlvPerMarket * marketCount; 486 | | uint256 glvDepositGasLimit = dataStore.getUint( 487 | | Keys.glvDepositGasLimitKey() 488 | | ); 489 | | 490 | | uint256 gasLimit = glvDepositGasLimit + 491 | | glvDeposit.callbackGasLimit() + 492 | | gasForGlvMarkets; 493 | | 494 | | if (glvDeposit.market() == glvDeposit.initialLongToken()) { 495 | | // user provided GM, no separate deposit will be created and executed in this case 496 | | return gasLimit; 497 | | } 498 | | 499 | | uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey()); 500 | | uint256 swapCount = glvDeposit.longTokenSwapPath().length + 501 | | glvDeposit.shortTokenSwapPath().length; 502 | | uint256 gasForSwaps = swapCount * gasPerSwap; 503 | | 504 | | if ( 505 | | glvDeposit.initialLongTokenAmount() == 0 || 506 | | glvDeposit.initialShortTokenAmount() == 0 507 | | ) { 508 | | return 509 | | gasLimit + 510 | | dataStore.getUint(Keys.depositGasLimitKey(true)) + 511 | | gasForSwaps; 512 | | } 513 | | return 514 | | gasLimit + 515 | | dataStore.getUint(Keys.depositGasLimitKey(false)) + 516 | | gasForSwaps; 517 | | } 518 | | 519 | * | function emitKeeperExecutionFee( 520 | | EventEmitter eventEmitter, 521 | | address keeper, 522 | | uint256 executionFeeAmount 523 | * | ) internal { 524 | * | EventUtils.EventLogData memory eventData; 525 | | 526 | * | eventData.addressItems.initItems(1); 527 | * | eventData.addressItems.setItem(0, "keeper", keeper); 528 | | 529 | * | eventData.uintItems.initItems(1); 530 | * | eventData.uintItems.setItem( 531 | * | 0, 532 | | "executionFeeAmount", 533 | * | executionFeeAmount 534 | | ); 535 | | 536 | * | eventEmitter.emitEventLog1( 537 | | "KeeperExecutionFee", 538 | * | Cast.toBytes32(keeper), 539 | * | eventData 540 | | ); 541 | | } 542 | | 543 | | function emitExecutionFeeRefund( 544 | | EventEmitter eventEmitter, 545 | | address receiver, 546 | | uint256 refundFeeAmount 547 | | ) internal { 548 | | EventUtils.EventLogData memory eventData; 549 | | 550 | | eventData.addressItems.initItems(1); 551 | | eventData.addressItems.setItem(0, "receiver", receiver); 552 | | 553 | | eventData.uintItems.initItems(1); 554 | | eventData.uintItems.setItem(0, "refundFeeAmount", refundFeeAmount); 555 | | 556 | | eventEmitter.emitEventLog1( 557 | | "ExecutionFeeRefund", 558 | | Cast.toBytes32(receiver), 559 | | eventData 560 | | ); 561 | | } 562 | | 563 | * | function emitExecutionFeeRefundCallback( 564 | | EventEmitter eventEmitter, 565 | | address callbackContract, 566 | | uint256 refundFeeAmount 567 | * | ) internal { 568 | * | EventUtils.EventLogData memory eventData; 569 | | 570 | * | eventData.addressItems.initItems(1); 571 | * | eventData.addressItems.setItem(0, "callbackContract", callbackContract); 572 | | 573 | * | eventData.uintItems.initItems(1); 574 | * | eventData.uintItems.setItem(0, "refundFeeAmount", refundFeeAmount); 575 | | 576 | * | eventEmitter.emitEventLog1( 577 | | "ExecutionFeeRefundCallback", 578 | * | Cast.toBytes32(callbackContract), 579 | * | eventData 580 | | ); 581 | | } 582 | | } 583 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/Glv.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | | import "../bank/StrictBank.sol"; 7 | | 8 | | contract Glv is ERC20, StrictBank { 9 | | constructor( 10 | | RoleStore _roleStore, 11 | | DataStore _dataStore 12 | | ) ERC20("GMX Liquidity Vault", "GLV") StrictBank(_roleStore, _dataStore) { 13 | | } 14 | | 15 | | function mint(address account, uint256 amount) external onlyController { 16 | | _mint(account, amount); 17 | | } 18 | | 19 | | function burn(address account, uint256 amount) external onlyController { 20 | | _burn(account, amount); 21 | | } 22 | | } 23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDeposit.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title GlvDeposit 6 | | // @dev Struct for GLV deposits 7 | * | library GlvDeposit { 8 | | // @dev there is a limit on the number of fields a struct can have when being passed 9 | | // or returned as a memory variable which can cause "Stack too deep" errors 10 | | // use sub-structs to avoid this issue 11 | | // @param addresses address values 12 | | // @param numbers number values 13 | | // @param flags boolean values 14 | | struct Props { 15 | | Addresses addresses; 16 | | Numbers numbers; 17 | | Flags flags; 18 | | } 19 | | 20 | | // @param account the account depositing liquidity 21 | | // @param receiver the address to send the liquidity tokens to 22 | | // @param callbackContract the callback contract 23 | | // @param uiFeeReceiver the ui fee receiver 24 | | // @param market the market to deposit to 25 | | struct Addresses { 26 | | address glv; 27 | | address account; 28 | | address receiver; 29 | | address callbackContract; 30 | | address uiFeeReceiver; 31 | | address market; 32 | | address initialLongToken; 33 | | address initialShortToken; 34 | | address[] longTokenSwapPath; 35 | | address[] shortTokenSwapPath; 36 | | } 37 | | 38 | | // @param initialLongTokenAmount the amount of long tokens to deposit 39 | | // @param initialShortTokenAmount the amount of short tokens to deposit 40 | | // @param minGlvTokens the minimum acceptable number of Glv tokens 41 | | // @param updatedAtBlock the block that the deposit was last updated at 42 | | // sending funds back to the user in case the deposit gets cancelled 43 | | // @param executionFee the execution fee for keepers 44 | | // @param callbackGasLimit the gas limit for the callbackContract 45 | | struct Numbers { 46 | | uint256 initialLongTokenAmount; 47 | | uint256 initialShortTokenAmount; 48 | | uint256 minGlvTokens; 49 | | uint256 updatedAtBlock; 50 | | uint256 updatedAtTime; 51 | | uint256 executionFee; 52 | | uint256 callbackGasLimit; 53 | | } 54 | | 55 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when 56 | | struct Flags { 57 | | bool shouldUnwrapNativeToken; 58 | | } 59 | | 60 | | 61 | | function account(Props memory props) internal pure returns (address) { 62 | | return props.addresses.account; 63 | | } 64 | | 65 | | function setAccount(Props memory props, address value) internal pure { 66 | | props.addresses.account = value; 67 | | } 68 | | 69 | | function receiver(Props memory props) internal pure returns (address) { 70 | | return props.addresses.receiver; 71 | | } 72 | | 73 | | function setReceiver(Props memory props, address value) internal pure { 74 | | props.addresses.receiver = value; 75 | | } 76 | | 77 | | function callbackContract(Props memory props) internal pure returns (address) { 78 | | return props.addresses.callbackContract; 79 | | } 80 | | 81 | | function setCallbackContract(Props memory props, address value) internal pure { 82 | | props.addresses.callbackContract = value; 83 | | } 84 | | 85 | | function uiFeeReceiver(Props memory props) internal pure returns (address) { 86 | | return props.addresses.uiFeeReceiver; 87 | | } 88 | | 89 | | function setUiFeeReceiver(Props memory props, address value) internal pure { 90 | | props.addresses.uiFeeReceiver = value; 91 | | } 92 | | 93 | | function glv(Props memory props) internal pure returns (address) { 94 | | return props.addresses.glv; 95 | | } 96 | | 97 | | function setGlv(Props memory props, address value) internal pure { 98 | | props.addresses.glv = value; 99 | | } 100 | | 101 | | function market(Props memory props) internal pure returns (address) { 102 | | return props.addresses.market; 103 | | } 104 | | 105 | | function setMarket(Props memory props, address value) internal pure { 106 | | props.addresses.market = value; 107 | | } 108 | | 109 | | function initialLongToken(Props memory props) internal pure returns (address) { 110 | | return props.addresses.initialLongToken; 111 | | } 112 | | 113 | | function setInitialLongToken(Props memory props, address value) internal pure { 114 | | props.addresses.initialLongToken = value; 115 | | } 116 | | 117 | | function initialShortToken(Props memory props) internal pure returns (address) { 118 | | return props.addresses.initialShortToken; 119 | | } 120 | | 121 | | function setInitialShortToken(Props memory props, address value) internal pure { 122 | | props.addresses.initialShortToken = value; 123 | | } 124 | | 125 | | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 126 | | return props.addresses.longTokenSwapPath; 127 | | } 128 | | 129 | | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure { 130 | | props.addresses.longTokenSwapPath = value; 131 | | } 132 | | 133 | | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 134 | | return props.addresses.shortTokenSwapPath; 135 | | } 136 | | 137 | | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure { 138 | | props.addresses.shortTokenSwapPath = value; 139 | | } 140 | | 141 | | function initialLongTokenAmount(Props memory props) internal pure returns (uint256) { 142 | | return props.numbers.initialLongTokenAmount; 143 | | } 144 | | 145 | | function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure { 146 | | props.numbers.initialLongTokenAmount = value; 147 | | } 148 | | 149 | | function initialShortTokenAmount(Props memory props) internal pure returns (uint256) { 150 | | return props.numbers.initialShortTokenAmount; 151 | | } 152 | | 153 | | function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure { 154 | | props.numbers.initialShortTokenAmount = value; 155 | | } 156 | | 157 | | function minGlvTokens(Props memory props) internal pure returns (uint256) { 158 | | return props.numbers.minGlvTokens; 159 | | } 160 | | 161 | | function setMinGlvTokens(Props memory props, uint256 value) internal pure { 162 | | props.numbers.minGlvTokens = value; 163 | | } 164 | | 165 | | function updatedAtBlock(Props memory props) internal pure returns (uint256) { 166 | | return props.numbers.updatedAtBlock; 167 | | } 168 | | 169 | | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure { 170 | | props.numbers.updatedAtBlock = value; 171 | | } 172 | | 173 | | function updatedAtTime(Props memory props) internal pure returns (uint256) { 174 | | return props.numbers.updatedAtTime; 175 | | } 176 | | 177 | | function setUpdatedAtTime(Props memory props, uint256 value) internal pure { 178 | | props.numbers.updatedAtTime = value; 179 | | } 180 | | 181 | | function executionFee(Props memory props) internal pure returns (uint256) { 182 | | return props.numbers.executionFee; 183 | | } 184 | | 185 | | function setExecutionFee(Props memory props, uint256 value) internal pure { 186 | | props.numbers.executionFee = value; 187 | | } 188 | | 189 | | function callbackGasLimit(Props memory props) internal pure returns (uint256) { 190 | | return props.numbers.callbackGasLimit; 191 | | } 192 | | 193 | | function setCallbackGasLimit(Props memory props, uint256 value) internal pure { 194 | | props.numbers.callbackGasLimit = value; 195 | | } 196 | | 197 | | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) { 198 | | return props.flags.shouldUnwrapNativeToken; 199 | | } 200 | | 201 | | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure { 202 | | props.flags.shouldUnwrapNativeToken = value; 203 | | } 204 | | } 205 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./GlvDeposit.sol"; 10 | | import "../pricing/ISwapPricingUtils.sol"; 11 | | 12 | * | library GlvDepositEventUtils { 13 | | using GlvDeposit for GlvDeposit.Props; 14 | | 15 | | using EventUtils for EventUtils.AddressItems; 16 | | using EventUtils for EventUtils.UintItems; 17 | | using EventUtils for EventUtils.IntItems; 18 | | using EventUtils for EventUtils.BoolItems; 19 | | using EventUtils for EventUtils.Bytes32Items; 20 | | using EventUtils for EventUtils.BytesItems; 21 | | using EventUtils for EventUtils.StringItems; 22 | | 23 | | function emitGlvDepositCreated( 24 | | EventEmitter eventEmitter, 25 | | bytes32 key, 26 | | GlvDeposit.Props memory glvDeposit 27 | | ) internal { 28 | | EventUtils.EventLogData memory eventData; 29 | | 30 | | eventData.addressItems.initItems(7); 31 | | eventData.addressItems.setItem(0, "account", glvDeposit.account()); 32 | | eventData.addressItems.setItem(1, "receiver", glvDeposit.receiver()); 33 | | eventData.addressItems.setItem(2, "callbackContract", glvDeposit.callbackContract()); 34 | | eventData.addressItems.setItem(3, "market", glvDeposit.market()); 35 | | eventData.addressItems.setItem(4, "glv", glvDeposit.glv()); 36 | | eventData.addressItems.setItem(5, "initialLongToken", glvDeposit.initialLongToken()); 37 | | eventData.addressItems.setItem(6, "initialShortToken", glvDeposit.initialShortToken()); 38 | | 39 | | eventData.addressItems.initArrayItems(2); 40 | | eventData.addressItems.setItem(0, "longTokenSwapPath", glvDeposit.longTokenSwapPath()); 41 | | eventData.addressItems.setItem(1, "shortTokenSwapPath", glvDeposit.shortTokenSwapPath()); 42 | | 43 | | eventData.uintItems.initItems(7); 44 | | eventData.uintItems.setItem(0, "initialLongTokenAmount", glvDeposit.initialLongTokenAmount()); 45 | | eventData.uintItems.setItem(1, "initialShortTokenAmount", glvDeposit.initialShortTokenAmount()); 46 | | eventData.uintItems.setItem(2, "minGlvTokens", glvDeposit.minGlvTokens()); 47 | | eventData.uintItems.setItem(3, "updatedAtBlock", glvDeposit.updatedAtBlock()); 48 | | eventData.uintItems.setItem(4, "updatedAtTime", glvDeposit.updatedAtTime()); 49 | | eventData.uintItems.setItem(5, "executionFee", glvDeposit.executionFee()); 50 | | eventData.uintItems.setItem(6, "callbackGasLimit", glvDeposit.callbackGasLimit()); 51 | | 52 | | eventData.boolItems.initItems(1); 53 | | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", glvDeposit.shouldUnwrapNativeToken()); 54 | | 55 | | eventData.bytes32Items.initItems(1); 56 | | eventData.bytes32Items.setItem(0, "key", key); 57 | | 58 | | eventEmitter.emitEventLog2( 59 | | "GlvDepositCreated", 60 | | key, 61 | | Cast.toBytes32(glvDeposit.account()), 62 | | eventData 63 | | ); 64 | | } 65 | | 66 | | function emitGlvDepositExecuted( 67 | | EventEmitter eventEmitter, 68 | | bytes32 key, 69 | | address account, 70 | | uint256 receivedMarketTokens 71 | | ) internal { 72 | | EventUtils.EventLogData memory eventData; 73 | | 74 | | eventData.bytes32Items.initItems(1); 75 | | eventData.bytes32Items.setItem(0, "key", key); 76 | | 77 | | eventData.addressItems.initItems(1); 78 | | eventData.addressItems.setItem(0, "account", account); 79 | | 80 | | eventData.uintItems.initItems(1); 81 | | eventData.uintItems.setItem(2, "receivedMarketTokens", receivedMarketTokens); 82 | | 83 | | eventEmitter.emitEventLog2( 84 | | "GlvDepositExecuted", 85 | | key, 86 | | Cast.toBytes32(account), 87 | | eventData 88 | | ); 89 | | } 90 | | 91 | | function emitGlvDepositCancelled( 92 | | EventEmitter eventEmitter, 93 | | bytes32 key, 94 | | address account, 95 | | string memory reason, 96 | | bytes memory reasonBytes 97 | | ) internal { 98 | | EventUtils.EventLogData memory eventData; 99 | | 100 | | eventData.bytes32Items.initItems(1); 101 | | eventData.bytes32Items.setItem(0, "key", key); 102 | | 103 | | eventData.addressItems.initItems(1); 104 | | eventData.addressItems.setItem(0, "account", account); 105 | | 106 | | eventData.stringItems.initItems(1); 107 | | eventData.stringItems.setItem(0, "reason", reason); 108 | | 109 | | eventData.bytesItems.initItems(1); 110 | | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 111 | | 112 | | eventEmitter.emitEventLog2( 113 | | "GlvDepositCancelled", 114 | | key, 115 | | Cast.toBytes32(account), 116 | | eventData 117 | | ); 118 | | } 119 | | } 120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./GlvDeposit.sol"; 9 | | 10 | | /** 11 | | * @title GlvDepositStoreUtils 12 | | * @dev Library for deposit storage functions 13 | | */ 14 | * | library GlvDepositStoreUtils { 15 | | using GlvDeposit for GlvDeposit.Props; 16 | | 17 | | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 18 | | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER")); 19 | | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT")); 20 | | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER")); 21 | | bytes32 internal constant GLV = keccak256(abi.encode("GLV")); 22 | | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET")); 23 | | bytes32 internal constant INITIAL_LONG_TOKEN = keccak256(abi.encode("INITIAL_LONG_TOKEN")); 24 | | bytes32 internal constant INITIAL_SHORT_TOKEN = keccak256(abi.encode("INITIAL_SHORT_TOKEN")); 25 | | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH")); 26 | | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH")); 27 | | 28 | | bytes32 internal constant INITIAL_LONG_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_LONG_TOKEN_AMOUNT")); 29 | | bytes32 internal constant INITIAL_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("INITIAL_SHORT_TOKEN_AMOUNT")); 30 | | bytes32 internal constant MIN_GLV_TOKENS = keccak256(abi.encode("MIN_GLV_TOKENS")); 31 | | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK")); 32 | | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME")); 33 | | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE")); 34 | | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT")); 35 | | 36 | | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN")); 37 | | 38 | | function get(DataStore dataStore, bytes32 key) internal view returns (GlvDeposit.Props memory) { 39 | | GlvDeposit.Props memory deposit; 40 | | if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) { 41 | | return deposit; 42 | | } 43 | | 44 | | deposit.setAccount(dataStore.getAddress( 45 | | keccak256(abi.encode(key, ACCOUNT)) 46 | | )); 47 | | 48 | | deposit.setReceiver(dataStore.getAddress( 49 | | keccak256(abi.encode(key, RECEIVER)) 50 | | )); 51 | | 52 | | deposit.setCallbackContract(dataStore.getAddress( 53 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 54 | | )); 55 | | 56 | | deposit.setUiFeeReceiver(dataStore.getAddress( 57 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 58 | | )); 59 | | 60 | | deposit.setGlv(dataStore.getAddress( 61 | | keccak256(abi.encode(key, GLV)) 62 | | )); 63 | | 64 | | deposit.setMarket(dataStore.getAddress( 65 | | keccak256(abi.encode(key, MARKET)) 66 | | )); 67 | | 68 | | deposit.setInitialLongToken(dataStore.getAddress( 69 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)) 70 | | )); 71 | | 72 | | deposit.setInitialShortToken(dataStore.getAddress( 73 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)) 74 | | )); 75 | | 76 | | deposit.setLongTokenSwapPath(dataStore.getAddressArray( 77 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 78 | | )); 79 | | 80 | | deposit.setShortTokenSwapPath(dataStore.getAddressArray( 81 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 82 | | )); 83 | | 84 | | deposit.setInitialLongTokenAmount(dataStore.getUint( 85 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)) 86 | | )); 87 | | 88 | | deposit.setInitialShortTokenAmount(dataStore.getUint( 89 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)) 90 | | )); 91 | | 92 | | deposit.setMinGlvTokens(dataStore.getUint( 93 | | keccak256(abi.encode(key, MIN_GLV_TOKENS)) 94 | | )); 95 | | 96 | | deposit.setUpdatedAtBlock(dataStore.getUint( 97 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 98 | | )); 99 | | 100 | | deposit.setUpdatedAtTime(dataStore.getUint( 101 | | keccak256(abi.encode(key, UPDATED_AT_TIME)) 102 | | )); 103 | | 104 | | deposit.setExecutionFee(dataStore.getUint( 105 | | keccak256(abi.encode(key, EXECUTION_FEE)) 106 | | )); 107 | | 108 | | deposit.setCallbackGasLimit(dataStore.getUint( 109 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 110 | | )); 111 | | 112 | | deposit.setShouldUnwrapNativeToken(dataStore.getBool( 113 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 114 | | )); 115 | | 116 | | return deposit; 117 | | } 118 | | 119 | | function set(DataStore dataStore, bytes32 key, GlvDeposit.Props memory glvDeposit) internal { 120 | | dataStore.addBytes32( 121 | | Keys.GLV_DEPOSIT_LIST, 122 | | key 123 | | ); 124 | | 125 | | dataStore.addBytes32( 126 | | Keys.accountGlvDepositListKey(glvDeposit.account()), 127 | | key 128 | | ); 129 | | 130 | | dataStore.setAddress( 131 | | keccak256(abi.encode(key, ACCOUNT)), 132 | | glvDeposit.account() 133 | | ); 134 | | 135 | | dataStore.setAddress( 136 | | keccak256(abi.encode(key, RECEIVER)), 137 | | glvDeposit.receiver() 138 | | ); 139 | | 140 | | dataStore.setAddress( 141 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)), 142 | | glvDeposit.callbackContract() 143 | | ); 144 | | 145 | | dataStore.setAddress( 146 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)), 147 | | glvDeposit.uiFeeReceiver() 148 | | ); 149 | | 150 | | dataStore.setAddress( 151 | | keccak256(abi.encode(key, GLV)), 152 | | glvDeposit.glv() 153 | | ); 154 | | 155 | | dataStore.setAddress( 156 | | keccak256(abi.encode(key, MARKET)), 157 | | glvDeposit.market() 158 | | ); 159 | | 160 | | dataStore.setAddress( 161 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)), 162 | | glvDeposit.initialLongToken() 163 | | ); 164 | | 165 | | dataStore.setAddress( 166 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)), 167 | | glvDeposit.initialShortToken() 168 | | ); 169 | | 170 | | dataStore.setAddressArray( 171 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)), 172 | | glvDeposit.longTokenSwapPath() 173 | | ); 174 | | 175 | | dataStore.setAddressArray( 176 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)), 177 | | glvDeposit.shortTokenSwapPath() 178 | | ); 179 | | 180 | | dataStore.setUint( 181 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)), 182 | | glvDeposit.initialLongTokenAmount() 183 | | ); 184 | | 185 | | dataStore.setUint( 186 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)), 187 | | glvDeposit.initialShortTokenAmount() 188 | | ); 189 | | 190 | | dataStore.setUint( 191 | | keccak256(abi.encode(key, MIN_GLV_TOKENS)), 192 | | glvDeposit.minGlvTokens() 193 | | ); 194 | | 195 | | dataStore.setUint( 196 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK)), 197 | | glvDeposit.updatedAtBlock() 198 | | ); 199 | | 200 | | dataStore.setUint( 201 | | keccak256(abi.encode(key, UPDATED_AT_TIME)), 202 | | glvDeposit.updatedAtTime() 203 | | ); 204 | | 205 | | dataStore.setUint( 206 | | keccak256(abi.encode(key, EXECUTION_FEE)), 207 | | glvDeposit.executionFee() 208 | | ); 209 | | 210 | | dataStore.setUint( 211 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)), 212 | | glvDeposit.callbackGasLimit() 213 | | ); 214 | | 215 | | dataStore.setBool( 216 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)), 217 | | glvDeposit.shouldUnwrapNativeToken() 218 | | ); 219 | | } 220 | | 221 | | function remove(DataStore dataStore, bytes32 key, address account) internal { 222 | | if (!dataStore.containsBytes32(Keys.GLV_DEPOSIT_LIST, key)) { 223 | | revert Errors.GlvDepositNotFound(key); 224 | | } 225 | | 226 | | dataStore.removeBytes32( 227 | | Keys.GLV_DEPOSIT_LIST, 228 | | key 229 | | ); 230 | | 231 | | dataStore.removeBytes32( 232 | | Keys.accountGlvDepositListKey(account), 233 | | key 234 | | ); 235 | | 236 | | dataStore.removeAddress( 237 | | keccak256(abi.encode(key, ACCOUNT)) 238 | | ); 239 | | 240 | | dataStore.removeAddress( 241 | | keccak256(abi.encode(key, RECEIVER)) 242 | | ); 243 | | 244 | | dataStore.removeAddress( 245 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 246 | | ); 247 | | 248 | | dataStore.removeAddress( 249 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 250 | | ); 251 | | 252 | | dataStore.removeAddress( 253 | | keccak256(abi.encode(key, GLV)) 254 | | ); 255 | | 256 | | dataStore.removeAddress( 257 | | keccak256(abi.encode(key, MARKET)) 258 | | ); 259 | | 260 | | dataStore.removeAddress( 261 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN)) 262 | | ); 263 | | 264 | | dataStore.removeAddress( 265 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN)) 266 | | ); 267 | | 268 | | dataStore.removeAddressArray( 269 | | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 270 | | ); 271 | | 272 | | dataStore.removeAddressArray( 273 | | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 274 | | ); 275 | | 276 | | dataStore.removeUint( 277 | | keccak256(abi.encode(key, INITIAL_LONG_TOKEN_AMOUNT)) 278 | | ); 279 | | 280 | | dataStore.removeUint( 281 | | keccak256(abi.encode(key, INITIAL_SHORT_TOKEN_AMOUNT)) 282 | | ); 283 | | 284 | | dataStore.removeUint( 285 | | keccak256(abi.encode(key, MIN_GLV_TOKENS)) 286 | | ); 287 | | 288 | | dataStore.removeUint( 289 | | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 290 | | ); 291 | | 292 | | dataStore.removeUint( 293 | | keccak256(abi.encode(key, UPDATED_AT_TIME)) 294 | | ); 295 | | 296 | | dataStore.removeUint( 297 | | keccak256(abi.encode(key, EXECUTION_FEE)) 298 | | ); 299 | | 300 | | dataStore.removeUint( 301 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 302 | | ); 303 | | 304 | | dataStore.removeBool( 305 | | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 306 | | ); 307 | | } 308 | | 309 | | function getGlvDepositCount(DataStore dataStore) internal view returns (uint256) { 310 | | return dataStore.getBytes32Count(Keys.GLV_DEPOSIT_LIST); 311 | | } 312 | | 313 | | function getGlvDepositKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 314 | | return dataStore.getBytes32ValuesAt(Keys.GLV_DEPOSIT_LIST, start, end); 315 | | } 316 | | 317 | | function getAccountGlvDepositCount(DataStore dataStore, address account) internal view returns (uint256) { 318 | | return dataStore.getBytes32Count(Keys.accountGlvDepositListKey(account)); 319 | | } 320 | | 321 | | function getAccountGlvDepositKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 322 | | return dataStore.getBytes32ValuesAt(Keys.accountGlvDepositListKey(account), start, end); 323 | | } 324 | | } 325 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvDepositUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../glv/Glv.sol"; 6 | | import "../glv/GlvVault.sol"; 7 | | import "../glv/GlvUtils.sol"; 8 | | import "../glv/GlvDeposit.sol"; 9 | | import "../glv/GlvDepositEventUtils.sol"; 10 | | import "../glv/GlvDepositStoreUtils.sol"; 11 | | import "../feature/FeatureUtils.sol"; 12 | | import "../deposit/DepositVault.sol"; 13 | | import "../deposit/ExecuteDepositUtils.sol"; 14 | | import "../deposit/DepositUtils.sol"; 15 | | import "../data/DataStore.sol"; 16 | | import "../oracle/Oracle.sol"; 17 | | import "../market/Market.sol"; 18 | | import "../market/MarketUtils.sol"; 19 | | import "../data/Keys.sol"; 20 | | import "../event/EventUtils.sol"; 21 | | 22 | * | library GlvDepositUtils { 23 | | using GlvDeposit for GlvDeposit.Props; 24 | | using Deposit for Deposit.Props; 25 | | using SafeCast for int256; 26 | | using EventUtils for EventUtils.UintItems; 27 | | 28 | | struct CreateGlvDepositParams { 29 | | address glv; 30 | | address receiver; 31 | | address callbackContract; 32 | | address uiFeeReceiver; 33 | | address market; 34 | | address initialLongToken; 35 | | address initialShortToken; 36 | | address[] longTokenSwapPath; 37 | | address[] shortTokenSwapPath; 38 | | uint256 minGlvTokens; 39 | | bool shouldUnwrapNativeToken; 40 | | uint256 executionFee; 41 | | uint256 callbackGasLimit; 42 | | } 43 | | 44 | | struct ExecuteGlvDepositParams { 45 | | DataStore dataStore; 46 | | EventEmitter eventEmitter; 47 | | GlvVault glvVault; 48 | | Oracle oracle; 49 | | bytes32 key; 50 | | uint256 startingGas; 51 | | address keeper; 52 | | } 53 | | 54 | | struct ExecuteGlvDepositCache { 55 | | uint256 requestExpirationTime; 56 | | uint256 maxOracleTimestamp; 57 | | uint256 receivedMarketTokens; 58 | | uint256 mintAmount; 59 | | uint256 marketCount; 60 | | uint256 oraclePriceCount; 61 | | } 62 | | 63 | | function createGlvDeposit( 64 | | DataStore dataStore, 65 | | EventEmitter eventEmitter, 66 | | GlvVault glvVault, 67 | | address account, 68 | | CreateGlvDepositParams memory params 69 | | ) internal returns (bytes32) { 70 | | AccountUtils.validateAccount(account); 71 | | GlvUtils.validateGlv(dataStore, params.glv); 72 | | GlvUtils.validateMarket(dataStore, params.glv, params.market, true); 73 | | 74 | | MarketUtils.validateEnabledMarket(dataStore, params.market); 75 | | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath); 76 | | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath); 77 | | 78 | | if (params.initialLongToken == params.market) { 79 | | // user deposited GM tokens 80 | | if (params.initialShortToken != address(0)) { 81 | | revert Errors.InvalidGlvDepositInitialShortToken(params.initialLongToken, params.initialShortToken); 82 | | } 83 | | if (params.longTokenSwapPath.length > 0 || params.longTokenSwapPath.length > 0) { 84 | | revert Errors.InvalidGlvDepositSwapPath( 85 | | params.longTokenSwapPath.length, 86 | | params.longTokenSwapPath.length 87 | | ); 88 | | } 89 | | } 90 | | 91 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would 92 | | // be non-zero, the initialShortTokenAmount would be zero 93 | | uint256 initialLongTokenAmount = glvVault.recordTransferIn(params.initialLongToken); 94 | | uint256 initialShortTokenAmount; 95 | | if (params.initialShortToken != address(0)) { 96 | | // initialShortToken could be zero address if user deposits GM token 97 | | initialShortTokenAmount = glvVault.recordTransferIn(params.initialShortToken); 98 | | } 99 | | 100 | | address wnt = TokenUtils.wnt(dataStore); 101 | | if (params.initialLongToken == wnt) { 102 | | initialLongTokenAmount -= params.executionFee; 103 | | } else if (params.initialShortToken == wnt) { 104 | | initialShortTokenAmount -= params.executionFee; 105 | | } else { 106 | | uint256 wntAmount = glvVault.recordTransferIn(wnt); 107 | | if (wntAmount < params.executionFee) { 108 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.executionFee); 109 | | } 110 | | 111 | | params.executionFee = wntAmount; 112 | | } 113 | | 114 | | if (initialLongTokenAmount == 0 && initialShortTokenAmount == 0) { 115 | | revert Errors.EmptyGlvDepositAmounts(); 116 | | } 117 | | 118 | | AccountUtils.validateReceiver(params.receiver); 119 | | 120 | | GlvDeposit.Props memory glvDeposit = GlvDeposit.Props( 121 | | GlvDeposit.Addresses({ 122 | | account: account, 123 | | glv: params.glv, 124 | | receiver: params.receiver, 125 | | callbackContract: params.callbackContract, 126 | | uiFeeReceiver: params.uiFeeReceiver, 127 | | market: params.market, 128 | | initialLongToken: params.initialLongToken, 129 | | initialShortToken: params.initialShortToken, 130 | | longTokenSwapPath: params.longTokenSwapPath, 131 | | shortTokenSwapPath: params.shortTokenSwapPath 132 | | }), 133 | | GlvDeposit.Numbers({ 134 | | initialLongTokenAmount: initialLongTokenAmount, 135 | | initialShortTokenAmount: initialShortTokenAmount, 136 | | minGlvTokens: params.minGlvTokens, 137 | | updatedAtBlock: Chain.currentBlockNumber(), 138 | | updatedAtTime: Chain.currentTimestamp(), 139 | | executionFee: params.executionFee, 140 | | callbackGasLimit: params.callbackGasLimit 141 | | }), 142 | | GlvDeposit.Flags({shouldUnwrapNativeToken: params.shouldUnwrapNativeToken}) 143 | | ); 144 | | 145 | | CallbackUtils.validateCallbackGasLimit(dataStore, params.callbackGasLimit); 146 | | 147 | | uint256 marketCount = GlvUtils.getMarketCount(dataStore, glvDeposit.glv()); 148 | | uint256 estimatedGasLimit = GasUtils.estimateExecuteGlvDepositGasLimit(dataStore, glvDeposit, marketCount); 149 | | uint256 oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount( 150 | | marketCount, 151 | | params.longTokenSwapPath.length + params.shortTokenSwapPath.length 152 | | ); 153 | | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount); 154 | | 155 | | bytes32 key = NonceUtils.getNextKey(dataStore); 156 | | 157 | | GlvDepositStoreUtils.set(dataStore, key, glvDeposit); 158 | | 159 | | GlvDepositEventUtils.emitGlvDepositCreated(eventEmitter, key, glvDeposit); 160 | | 161 | | return key; 162 | | } 163 | | 164 | | function executeGlvDeposit( 165 | | ExecuteGlvDepositParams memory params, 166 | | GlvDeposit.Props memory glvDeposit 167 | | ) internal returns (uint256) { 168 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 169 | | params.startingGas -= gasleft() / 63; 170 | | 171 | | GlvDepositStoreUtils.remove(params.dataStore, params.key, glvDeposit.account()); 172 | | 173 | | if (glvDeposit.account() == address(0)) { 174 | | revert Errors.EmptyGlvDeposit(); 175 | | } 176 | | 177 | | if (params.oracle.minTimestamp() < glvDeposit.updatedAtTime()) { 178 | | revert Errors.OracleTimestampsAreSmallerThanRequired( 179 | | params.oracle.minTimestamp(), 180 | | glvDeposit.updatedAtTime() 181 | | ); 182 | | } 183 | | 184 | | ExecuteGlvDepositCache memory cache; 185 | | 186 | | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 187 | | cache.maxOracleTimestamp = params.oracle.maxTimestamp(); 188 | | 189 | | if (cache.maxOracleTimestamp > glvDeposit.updatedAtTime() + cache.requestExpirationTime) { 190 | | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 191 | | cache.maxOracleTimestamp, 192 | | glvDeposit.updatedAtTime(), 193 | | cache.requestExpirationTime 194 | | ); 195 | | } 196 | | 197 | | cache.receivedMarketTokens = _processMarketDeposit(params, glvDeposit); 198 | | cache.mintAmount = _getMintAmount(params.dataStore, params.oracle, glvDeposit, cache.receivedMarketTokens); 199 | | 200 | | if (cache.mintAmount < glvDeposit.minGlvTokens()) { 201 | | revert Errors.MinMarketTokens(cache.mintAmount, glvDeposit.minGlvTokens()); 202 | | } 203 | | 204 | | Glv(payable(glvDeposit.glv())).mint(glvDeposit.receiver(), cache.mintAmount); 205 | | 206 | | GlvDepositEventUtils.emitGlvDepositExecuted( 207 | | params.eventEmitter, 208 | | params.key, 209 | | glvDeposit.account(), 210 | | cache.mintAmount 211 | | ); 212 | | 213 | | cache.marketCount = GlvUtils.getMarketCount(params.dataStore, glvDeposit.glv()); 214 | | cache.oraclePriceCount = GasUtils.estimateGlvDepositOraclePriceCount( 215 | | cache.marketCount, 216 | | glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length 217 | | ); 218 | | GasUtils.payExecutionFee( 219 | | params.dataStore, 220 | | params.eventEmitter, 221 | | params.glvVault, 222 | | params.key, 223 | | glvDeposit.callbackContract(), 224 | | glvDeposit.executionFee(), 225 | | params.startingGas, 226 | | cache.oraclePriceCount, 227 | | params.keeper, 228 | | glvDeposit.receiver() 229 | | ); 230 | | 231 | | EventUtils.EventLogData memory eventData; 232 | | eventData.uintItems.initItems(1); 233 | | eventData.uintItems.setItem(0, "receivedGlvTokens", cache.mintAmount); 234 | | CallbackUtils.afterGlvDepositExecution(params.key, glvDeposit, eventData); 235 | | 236 | | return cache.mintAmount; 237 | | } 238 | | 239 | | function _getMintAmount( 240 | | DataStore dataStore, 241 | | Oracle oracle, 242 | | GlvDeposit.Props memory glvDeposit, 243 | | uint256 receivedMarketTokens 244 | | ) internal view returns (uint256) { 245 | | Market.Props memory market = MarketUtils.getEnabledMarket(dataStore, glvDeposit.market()); 246 | | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 247 | | dataStore, 248 | | market, 249 | | oracle.getPrimaryPrice(market.indexToken), 250 | | oracle.getPrimaryPrice(market.longToken), 251 | | oracle.getPrimaryPrice(market.shortToken), 252 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 253 | | false // maximize 254 | | ); 255 | | uint256 receivedMarketTokensUsd = MarketUtils.marketTokenAmountToUsd( 256 | | receivedMarketTokens, 257 | | poolValueInfo.poolValue.toUint256(), 258 | | ERC20(market.marketToken).totalSupply() 259 | | ); 260 | | 261 | | Glv glv = Glv(payable(glvDeposit.glv())); 262 | | uint256 glvValue = GlvUtils.getValue(dataStore, oracle, glv); 263 | | uint256 glvSupply = glv.totalSupply(); 264 | | return GlvUtils.usdToGlvTokenAmount(receivedMarketTokensUsd, glvValue, glvSupply); 265 | | } 266 | | 267 | | function _processMarketDeposit( 268 | | ExecuteGlvDepositParams memory params, 269 | | GlvDeposit.Props memory glvDeposit 270 | | ) private returns (uint256) { 271 | | if (glvDeposit.market() == glvDeposit.initialLongToken()) { 272 | | // user deposited GM tokens 273 | | return glvDeposit.initialLongTokenAmount(); 274 | | } 275 | | 276 | | Deposit.Props memory deposit = Deposit.Props( 277 | | Deposit.Addresses({ 278 | | account: glvDeposit.account(), 279 | | receiver: glvDeposit.receiver(), 280 | | callbackContract: address(0), 281 | | uiFeeReceiver: glvDeposit.uiFeeReceiver(), 282 | | market: glvDeposit.market(), 283 | | initialLongToken: glvDeposit.initialLongToken(), 284 | | initialShortToken: glvDeposit.initialShortToken(), 285 | | longTokenSwapPath: new address[](0), 286 | | shortTokenSwapPath: new address[](0) 287 | | }), 288 | | Deposit.Numbers({ 289 | | initialLongTokenAmount: glvDeposit.initialLongTokenAmount(), 290 | | initialShortTokenAmount: glvDeposit.initialShortTokenAmount(), 291 | | minMarketTokens: 0, 292 | | updatedAtBlock: 0, 293 | | updatedAtTime: glvDeposit.updatedAtTime(), 294 | | executionFee: 0, 295 | | callbackGasLimit: 0 296 | | }), 297 | | Deposit.Flags({shouldUnwrapNativeToken: false}) 298 | | ); 299 | | 300 | | bytes32 depositKey = NonceUtils.getNextKey(params.dataStore); 301 | | params.dataStore.addBytes32(Keys.DEPOSIT_LIST, depositKey); 302 | | DepositEventUtils.emitDepositCreated(params.eventEmitter, depositKey, deposit, DepositUtils.DepositType.Glv); 303 | | 304 | | ExecuteDepositUtils.ExecuteDepositParams memory executeDepositParams = ExecuteDepositUtils.ExecuteDepositParams( 305 | | params.dataStore, 306 | | params.eventEmitter, 307 | | DepositVault(payable(params.glvVault)), 308 | | params.oracle, 309 | | depositKey, 310 | | params.keeper, 311 | | params.startingGas, 312 | | ISwapPricingUtils.SwapPricingType.TwoStep, 313 | | true // includeVirtualInventoryImpact 314 | | ); 315 | | 316 | | return ExecuteDepositUtils.executeDeposit(executeDepositParams, deposit); 317 | | } 318 | | 319 | | function cancelGlvDeposit( 320 | | DataStore dataStore, 321 | | EventEmitter eventEmitter, 322 | | GlvVault glvVault, 323 | | bytes32 key, 324 | | address keeper, 325 | | uint256 startingGas, 326 | | string memory reason, 327 | | bytes memory reasonBytes 328 | | ) internal { 329 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 330 | | startingGas -= gasleft() / 63; 331 | | 332 | | GlvDeposit.Props memory glvDeposit = GlvDepositStoreUtils.get(dataStore, key); 333 | | if (glvDeposit.account() == address(0)) { 334 | | revert Errors.EmptyGlvDeposit(); 335 | | } 336 | | 337 | | if (glvDeposit.initialLongTokenAmount() == 0 && glvDeposit.initialShortTokenAmount() == 0) { 338 | | revert Errors.EmptyGlvDepositAmounts(); 339 | | } 340 | | 341 | | GlvDepositStoreUtils.remove(dataStore, key, glvDeposit.account()); 342 | | 343 | | if (glvDeposit.initialLongTokenAmount() > 0) { 344 | | glvVault.transferOut( 345 | | glvDeposit.initialLongToken(), 346 | | glvDeposit.account(), 347 | | glvDeposit.initialLongTokenAmount(), 348 | | glvDeposit.shouldUnwrapNativeToken() 349 | | ); 350 | | } 351 | | 352 | | if (glvDeposit.initialShortTokenAmount() > 0) { 353 | | glvVault.transferOut( 354 | | glvDeposit.initialShortToken(), 355 | | glvDeposit.account(), 356 | | glvDeposit.initialShortTokenAmount(), 357 | | glvDeposit.shouldUnwrapNativeToken() 358 | | ); 359 | | } 360 | | 361 | | GlvDepositEventUtils.emitGlvDepositCancelled(eventEmitter, key, glvDeposit.account(), reason, reasonBytes); 362 | | 363 | | uint256 marketCount = GlvUtils.getMarketCount(dataStore, glvDeposit.glv()); 364 | | GasUtils.payExecutionFee( 365 | | dataStore, 366 | | eventEmitter, 367 | | glvVault, 368 | | key, 369 | | glvDeposit.callbackContract(), 370 | | glvDeposit.executionFee(), 371 | | startingGas, 372 | | GasUtils.estimateGlvDepositOraclePriceCount( 373 | | marketCount, 374 | | glvDeposit.longTokenSwapPath().length + glvDeposit.shortTokenSwapPath().length 375 | | ), 376 | | keeper, 377 | | glvDeposit.receiver() 378 | | ); 379 | | 380 | | EventUtils.EventLogData memory eventData; 381 | | CallbackUtils.afterGlvDepositCancellation(key, glvDeposit, eventData); 382 | | } 383 | | } 384 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../glv/Glv.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../oracle/Oracle.sol"; 8 | | import "../market/Market.sol"; 9 | | import "../market/MarketUtils.sol"; 10 | | import "../shift/ShiftUtils.sol"; 11 | | import "../exchange/IShiftHandler.sol"; 12 | | import "../market/MarketPoolValueInfo.sol"; 13 | | 14 | * | library GlvUtils { 15 | | using SafeCast for int256; 16 | | 17 | | // @dev get the USD value of the Glv 18 | | // @param dataStore DataStore 19 | | // @param oracle Oracle 20 | | // @param glv Glv 21 | | // @return the USD value of the Glv 22 | | function getValue(DataStore dataStore, Oracle oracle, Glv glv) internal view returns (uint256 glvValue) { 23 | | address[] memory markets = new address[](2); 24 | | for (uint256 i = 0; i < markets.length; i++) { 25 | | address marketAddress = markets[i]; 26 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); 27 | | (int256 marketTokenPrice, ) = MarketUtils.getMarketTokenPrice( 28 | | dataStore, 29 | | market, 30 | | oracle.getPrimaryPrice(market.indexToken), 31 | | oracle.getPrimaryPrice(market.longToken), 32 | | oracle.getPrimaryPrice(market.shortToken), 33 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 34 | | true // maximize 35 | | ); 36 | | 37 | | if (marketTokenPrice < 0) { 38 | | revert Errors.InvalidMarketTokenPrice(marketAddress, marketTokenPrice); 39 | | } 40 | | 41 | | uint256 balance = IERC20(marketAddress).balanceOf(address(glv)); 42 | | 43 | | glvValue += balance * marketTokenPrice.toUint256(); 44 | | } 45 | | } 46 | | 47 | | // @dev convert a USD value to number of glv tokens 48 | | // @param usdValue the input USD value 49 | | // @param glvValue the value of the pool 50 | | // @param supply the supply of glv tokens 51 | | // @return the number of glv tokens 52 | | function usdToGlvTokenAmount(uint256 usdValue, uint256 glvValue, uint256 supply) internal pure returns (uint256) { 53 | | // if the supply and glvValue is zero, use 1 USD as the token price 54 | | if (supply == 0 && glvValue == 0) { 55 | | return Precision.floatToWei(usdValue); 56 | | } 57 | | 58 | | // if the supply is zero and the glvValue is more than zero, 59 | | // then include the glvValue for the amount of tokens minted so that 60 | | // the glv token price after mint would be 1 USD 61 | | // TODO: copy-pasted from MarketUtils, is it correct for glv? 62 | | if (supply == 0 && glvValue > 0) { 63 | | return Precision.floatToWei(glvValue + usdValue); 64 | | } 65 | | 66 | | // round glv tokens down 67 | | return Precision.mulDiv(supply, usdValue, glvValue); 68 | | } 69 | | 70 | | function validateMarket(DataStore dataStore, address glv, address market, bool shouldBeEnabled) internal view { 71 | | if (!dataStore.containsAddress(Keys.glvSupportedMarketListKey(glv), market)) { 72 | | revert Errors.GlvUnsupportedMarket(glv, market); 73 | | } 74 | | 75 | | if (shouldBeEnabled) { 76 | | if (dataStore.getBool(Keys.isGlvMarketDisabledKey(glv, market))) { 77 | | revert Errors.GlvDisabledMarket(glv, market); 78 | | } 79 | | } 80 | | } 81 | | 82 | | function validateGlv(DataStore dataStore, address glv) internal view { 83 | | if (!dataStore.containsAddress(Keys.GLV_LIST, glv)) { 84 | | revert Errors.EmptyGlv(glv); 85 | | } 86 | | } 87 | | 88 | | function getMarketCount(DataStore dataStore, address glv) internal view returns (uint256) { 89 | | return dataStore.getAddressCount(Keys.glvSupportedMarketListKey(glv)); 90 | | } 91 | | 92 | | function createShift( 93 | | DataStore dataStore, 94 | | Oracle oracle, 95 | | IShiftHandler shiftHandler, 96 | | ShiftVault shiftVault, 97 | | address account, 98 | | address glv, 99 | | uint256 marketTokenAmount, 100 | | ShiftUtils.CreateShiftParams memory params 101 | | ) internal { 102 | | validateGlv(dataStore, glv); 103 | | 104 | | validateMarket(dataStore, glv, params.fromMarket, false); 105 | | validateMarket(dataStore, glv, params.toMarket, true); 106 | | 107 | | if (params.receiver != address(glv)) { 108 | | revert Errors.GlvInvalidReceiver(address(glv), params.receiver); 109 | | } 110 | | if (params.callbackContract != address(this)) { 111 | | revert Errors.GlvInvalidCallbackContract(address(glv), params.callbackContract); 112 | | } 113 | | 114 | | Market.Props memory fromMarket = MarketStoreUtils.get(dataStore, params.fromMarket); 115 | | uint256 marketTokenBalance = ERC20(fromMarket.marketToken).balanceOf(glv); 116 | | if (marketTokenBalance < marketTokenAmount) { 117 | | revert Errors.GlvInsufficientMarketTokenBalance( 118 | | glv, 119 | | fromMarket.marketToken, 120 | | marketTokenBalance, 121 | | marketTokenAmount 122 | | ); 123 | | } 124 | | 125 | | validatePendingShift(dataStore, glv); 126 | | 127 | | Market.Props memory toMarket = MarketStoreUtils.get(dataStore, params.fromMarket); 128 | | validateMaxMarketTokenBalance(dataStore, oracle, glv, toMarket, marketTokenAmount); 129 | | 130 | | TokenUtils.transfer(dataStore, fromMarket.marketToken, address(shiftVault), marketTokenAmount); 131 | | bytes32 shiftKey = shiftHandler.createShift(account, params); 132 | | 133 | | setPendingShift(dataStore, glv, shiftKey); 134 | | } 135 | | 136 | | function validatePendingShift(DataStore dataStore, address glv) internal view { 137 | | bytes32 shiftKey = dataStore.getBytes32(Keys.glvPendingShiftKey(glv)); 138 | | if (shiftKey != bytes32(0)) { 139 | | revert Errors.GlvHasPendingShift(glv); 140 | | } 141 | | } 142 | | 143 | | function setPendingShift(DataStore dataStore, address glv, bytes32 shiftKey) internal { 144 | | dataStore.setBytes32(Keys.glvPendingShiftKey(glv), shiftKey); 145 | | dataStore.setAddress(Keys.glvPendingShiftBackrefKey(shiftKey), glv); 146 | | } 147 | | 148 | | function clearPendingShift(DataStore dataStore, bytes32 shiftKey) internal { 149 | | address glv = dataStore.getAddress(Keys.glvPendingShiftBackrefKey(shiftKey)); 150 | | if (glv == address(0)) { 151 | | revert Errors.GlvShiftNotFound(shiftKey); 152 | | } 153 | | dataStore.removeAddress(Keys.glvPendingShiftBackrefKey(shiftKey)); 154 | | dataStore.removeBytes32(Keys.glvPendingShiftKey(glv)); 155 | | } 156 | | 157 | | function validateMaxMarketTokenBalance( 158 | | DataStore dataStore, 159 | | Oracle oracle, 160 | | address glv, 161 | | Market.Props memory market, 162 | | uint256 marketTokenAmount 163 | | ) internal view { 164 | | uint256 maxMarketTokenBalanceUsd = getGlvMaxMarketTokenBalanceUsd(dataStore, glv, market.marketToken); 165 | | if (maxMarketTokenBalanceUsd == 0) { 166 | | return; 167 | | } 168 | | 169 | | MarketPoolValueInfo.Props memory fromMarketPoolValueInfo = MarketUtils.getPoolValueInfo( 170 | | dataStore, 171 | | market, 172 | | oracle.getPrimaryPrice(market.indexToken), 173 | | oracle.getPrimaryPrice(market.longToken), 174 | | oracle.getPrimaryPrice(market.shortToken), 175 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 176 | | true // maximize 177 | | ); 178 | | 179 | | uint256 marketTokenSupply = ERC20(market.marketToken).totalSupply(); 180 | | uint256 marketTokenUsd = MarketUtils.marketTokenAmountToUsd( 181 | | marketTokenAmount, 182 | | fromMarketPoolValueInfo.poolValue.toUint256(), 183 | | marketTokenSupply 184 | | ); 185 | | uint256 marketTokenBalanceUsd = MarketUtils.marketTokenAmountToUsd( 186 | | ERC20(market.marketToken).balanceOf(glv), 187 | | fromMarketPoolValueInfo.poolValue.toUint256(), 188 | | marketTokenSupply 189 | | ); 190 | | uint256 nextMarketTokenBalanceUsd = marketTokenBalanceUsd + marketTokenUsd; 191 | | if (nextMarketTokenBalanceUsd > maxMarketTokenBalanceUsd) { 192 | | revert Errors.GlvMaxMarketTokenBalanceExceeded( 193 | | glv, 194 | | market.marketToken, 195 | | maxMarketTokenBalanceUsd, 196 | | nextMarketTokenBalanceUsd 197 | | ); 198 | | } 199 | | } 200 | | 201 | | function getGlvMaxMarketTokenBalanceUsd( 202 | | DataStore dataStore, 203 | | address glv, 204 | | address market 205 | | ) internal view returns (uint256) { 206 | | return dataStore.getUint(Keys.glvMaxMarketTokenBalanceUsdKey(glv, market)); 207 | | } 208 | | 209 | | function addMarket(DataStore dataStore, address glv, address market) internal { 210 | | GlvUtils.validateGlv(dataStore, glv); 211 | | MarketUtils.validateEnabledMarket(dataStore, market); 212 | | 213 | | bytes32 key = Keys.glvSupportedMarketListKey(glv); 214 | | if (dataStore.containsAddress(key, market)) { 215 | | revert Errors.GlvMarketAlreadyExists(glv, market); 216 | | } 217 | | dataStore.addAddress(key, market); 218 | | } 219 | | 220 | | function disableMarket(DataStore dataStore, address glv, address market) internal { 221 | | GlvUtils.validateGlv(dataStore, glv); 222 | | bytes32 key = Keys.glvSupportedMarketListKey(glv); 223 | | if (!dataStore.containsAddress(key, market)) { 224 | | revert Errors.GlvUnsupportedMarket(glv, market); 225 | | } 226 | | 227 | | dataStore.setBool(Keys.isGlvMarketDisabledKey(glv, market), true); 228 | | } 229 | | } 230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/glv/GlvVault.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../bank/StrictBank.sol"; 6 | | 7 | * | contract GlvVault is StrictBank { 8 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {} 9 | | } 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/GovTimelockController.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/governance/TimelockController.sol"; 6 | | 7 | * | contract GovTimelockController is TimelockController { 8 | | string private _name; 9 | | 10 | | constructor( 11 | | string memory name_, 12 | | uint256 minDelay, 13 | | address[] memory proposers, 14 | | address[] memory executors, 15 | | address admin 16 | | ) TimelockController(minDelay, proposers, executors, admin) { 17 | | _name = name_; 18 | | } 19 | | 20 | | function name() public view returns (string memory) { 21 | | return _name; 22 | | } 23 | | } 24 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/GovToken.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; 7 | | import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; 8 | | 9 | | import "../chain/Chain.sol"; 10 | | import "../role/RoleModule.sol"; 11 | | 12 | * | contract GovToken is ERC20, ERC20Permit, ERC20Votes, RoleModule { 13 | | uint8 private _decimals; 14 | | 15 | | constructor( 16 | | RoleStore roleStore_, 17 | | string memory name_, 18 | | string memory symbol_, 19 | | uint8 decimals_ 20 | | ) 21 | | ERC20(name_, symbol_) 22 | | ERC20Permit(name_) 23 | | RoleModule(roleStore_) 24 | | { 25 | | _decimals = decimals_; 26 | | } 27 | | 28 | | function clock() public view override returns (uint48) { 29 | | return SafeCast.toUint48(Chain.currentTimestamp()); 30 | | } 31 | | 32 | | // solhint-disable-next-line func-name-mixedcase 33 | | function CLOCK_MODE() public view override returns (string memory) { 34 | | // Check that the clock was not modified 35 | | require(clock() == Chain.currentTimestamp(), "ERC20Votes: broken clock mode"); 36 | | return "mode=timestamp"; 37 | | } 38 | | 39 | | function decimals() public view override returns (uint8) { 40 | | return _decimals; 41 | | } 42 | | 43 | | // @dev mint tokens to an account 44 | | // @param account the account to mint to 45 | | // @param amount the amount of tokens to mint 46 | | function mint(address account, uint256 amount) external onlyGovTokenController { 47 | | _mint(account, amount); 48 | | } 49 | | 50 | | // @dev burn tokens from an account 51 | | // @param account the account to burn tokens for 52 | | // @param amount the amount of tokens to burn 53 | | function burn(address account, uint256 amount) external onlyGovTokenController { 54 | | _burn(account, amount); 55 | | } 56 | | 57 | | function _transfer(address from, address to, uint256 amount) internal override { 58 | | // only allow GOV_TOKEN_CONTROLLERs to make transfers 59 | | // the user would need to approve the GOV_TOKEN_CONTROLLER contract 60 | | // the GOV_TOKEN_CONTROLLER contract can then call transferFrom to transfer tokens 61 | | _validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER"); 62 | | 63 | | super._transfer(from, to, amount); 64 | | } 65 | | 66 | | // The functions below are overrides required by Solidity. 67 | | 68 | | function _afterTokenTransfer(address from, address to, uint256 amount) internal override(ERC20, ERC20Votes) { 69 | | super._afterTokenTransfer(from, to, amount); 70 | | } 71 | | 72 | | function _mint(address to, uint256 amount) internal override(ERC20, ERC20Votes) { 73 | | super._mint(to, amount); 74 | | } 75 | | 76 | | function _burn(address account, uint256 amount) internal override(ERC20, ERC20Votes) { 77 | | super._burn(account, amount); 78 | | } 79 | | } 80 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/gov/ProtocolGovernor.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/governance/Governor.sol"; 6 | | import "@openzeppelin/contracts/governance/compatibility/GovernorCompatibilityBravo.sol"; 7 | | import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol"; 8 | | import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol"; 9 | | import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol"; 10 | | import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol"; 11 | | 12 | | import "../chain/Chain.sol"; 13 | | 14 | * | contract ProtocolGovernor is 15 | | Governor, 16 | | GovernorSettings, 17 | | GovernorCompatibilityBravo, 18 | | GovernorVotes, 19 | | GovernorVotesQuorumFraction, 20 | | GovernorTimelockControl 21 | | { 22 | | 23 | | string private _version; 24 | | 25 | | constructor( 26 | | IVotes token_, 27 | | TimelockController timelock_, 28 | | string memory name_, 29 | | string memory version_, 30 | | uint256 votingDelay_, 31 | | uint256 votingPeriod_, 32 | | uint256 proposalThreshold_, 33 | | uint256 quorumNumeratorValue_ 34 | | ) 35 | | Governor(name_) 36 | | GovernorVotes(token_) 37 | | GovernorSettings(votingDelay_, votingPeriod_, proposalThreshold_) 38 | | GovernorVotesQuorumFraction(quorumNumeratorValue_) 39 | | GovernorTimelockControl(timelock_) 40 | | { 41 | | _version = version_; 42 | | } 43 | | 44 | | function clock() public view override(GovernorVotes, IGovernor) returns (uint48) { 45 | | return SafeCast.toUint48(Chain.currentTimestamp()); 46 | | } 47 | | 48 | | // solhint-disable-next-line func-name-mixedcase 49 | | function CLOCK_MODE() public view override(GovernorVotes, IGovernor) returns (string memory) { 50 | | // Check that the clock was not modified 51 | | require(clock() == Chain.currentTimestamp(), "ERC20Votes: broken clock mode"); 52 | | return "mode=timestamp"; 53 | | } 54 | | 55 | | function version() public view override(Governor, IGovernor) returns (string memory) { 56 | | return _version; 57 | | } 58 | | 59 | | // The functions below are overrides required by Solidity. 60 | | 61 | | function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) { 62 | | return super.proposalThreshold(); 63 | | } 64 | | 65 | | function state( 66 | | uint256 proposalId 67 | | ) public view override(Governor, IGovernor, GovernorTimelockControl) returns (ProposalState) { 68 | | return super.state(proposalId); 69 | | } 70 | | 71 | | function propose( 72 | | address[] memory targets, 73 | | uint256[] memory values, 74 | | bytes[] memory calldatas, 75 | | string memory description 76 | | ) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) { 77 | | return super.propose(targets, values, calldatas, description); 78 | | } 79 | | 80 | | function cancel( 81 | | address[] memory targets, 82 | | uint256[] memory values, 83 | | bytes[] memory calldatas, 84 | | bytes32 descriptionHash 85 | | ) public override(Governor, GovernorCompatibilityBravo, IGovernor) returns (uint256) { 86 | | return super.cancel(targets, values, calldatas, descriptionHash); 87 | | } 88 | | 89 | | function _execute( 90 | | uint256 proposalId, 91 | | address[] memory targets, 92 | | uint256[] memory values, 93 | | bytes[] memory calldatas, 94 | | bytes32 descriptionHash 95 | | ) internal override(Governor, GovernorTimelockControl) { 96 | | super._execute(proposalId, targets, values, calldatas, descriptionHash); 97 | | } 98 | | 99 | | function _cancel( 100 | | address[] memory targets, 101 | | uint256[] memory values, 102 | | bytes[] memory calldatas, 103 | | bytes32 descriptionHash 104 | | ) internal override(Governor, GovernorTimelockControl) returns (uint256) { 105 | | return super._cancel(targets, values, calldatas, descriptionHash); 106 | | } 107 | | 108 | | function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) { 109 | | return super._executor(); 110 | | } 111 | | 112 | | function supportsInterface( 113 | | bytes4 interfaceId 114 | | ) public view override(Governor, IERC165, GovernorTimelockControl) returns (bool) { 115 | | return super.supportsInterface(interfaceId); 116 | | } 117 | | } 118 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/liquidation/LiquidationUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../position/PositionUtils.sol"; 6 | | import "../position/PositionStoreUtils.sol"; 7 | | import "../order/OrderStoreUtils.sol"; 8 | | import "../order/OrderEventUtils.sol"; 9 | | import "../nonce/NonceUtils.sol"; 10 | | import "../callback/CallbackUtils.sol"; 11 | | 12 | | // @title LiquidationUtils 13 | | // @dev Library to help with liquidations 14 | * | library LiquidationUtils { 15 | | using Position for Position.Props; 16 | | using Order for Order.Props; 17 | | 18 | | // @dev creates a liquidation order for a position 19 | | // @param dataStore DataStore 20 | | // @param account the position's account 21 | | // @param market the position's market 22 | | // @param collateralToken the position's collateralToken 23 | | // @param isLong whether the position is long or short 24 | * | function createLiquidationOrder( 25 | | DataStore dataStore, 26 | | EventEmitter eventEmitter, 27 | | address account, 28 | | address market, 29 | | address collateralToken, 30 | | bool isLong 31 | * | ) internal returns (bytes32) { 32 | * | bytes32 positionKey = Position.getPositionKey(account, market, collateralToken, isLong); 33 | * | Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey); 34 | | 35 | * | Order.Addresses memory addresses = Order.Addresses( 36 | * | account, // account 37 | * | account, // receiver 38 | * | account, // cancellationReceiver 39 | * | CallbackUtils.getSavedCallbackContract(dataStore, account, market), // callbackContract 40 | * | address(0), // uiFeeReceiver 41 | * | market, // market 42 | * | position.collateralToken(), // initialCollateralToken 43 | * | new address[](0) // swapPath 44 | | ); 45 | | 46 | | // no slippage is set for this order, in case of a liquidation the amount 47 | | // of collateral being swapped should not be too large 48 | | // in case of large price impact, the user could be refunded 49 | | // through a protocol fund if required, this amount could later be claimed 50 | | // from the price impact pool, this claiming process should be added if 51 | | // required 52 | | // 53 | | // setting a maximum price impact that will work for majority of cases 54 | | // may also be challenging since the price impact would vary based on the 55 | | // amount of collateral being swapped 56 | | // 57 | | // note that the decreasePositionSwapType should be SwapPnlTokenToCollateralToken 58 | | // because fees are calculated with reference to the collateral token 59 | | // fees are deducted from the output amount if the output token is the same as the 60 | | // collateral token 61 | | // swapping the pnl token to the collateral token helps to ensure fees can be paid 62 | | // using the realized profit 63 | * | Order.Numbers memory numbers = Order.Numbers( 64 | * | Order.OrderType.Liquidation, // orderType 65 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken, // decreasePositionSwapType 66 | * | position.sizeInUsd(), // sizeDeltaUsd 67 | * | 0, // initialCollateralDeltaAmount 68 | * | 0, // triggerPrice 69 | * | position.isLong() ? 0 : type(uint256).max, // acceptablePrice 70 | * | 0, // executionFee 71 | * | dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT), // callbackGasLimit 72 | * | 0, // minOutputAmount 73 | * | Chain.currentBlockNumber(), // updatedAtBlock 74 | * | Chain.currentTimestamp() // updatedAtTime 75 | | ); 76 | | 77 | * | Order.Flags memory flags = Order.Flags( 78 | * | position.isLong(), // isLong 79 | * | true, // shouldUnwrapNativeToken 80 | * | false, // isFrozen 81 | * | false // autoCancel 82 | | ); 83 | | 84 | * | Order.Props memory order = Order.Props( 85 | * | addresses, 86 | * | numbers, 87 | * | flags 88 | | ); 89 | | 90 | * | bytes32 key = NonceUtils.getNextKey(dataStore); 91 | * | OrderStoreUtils.set(dataStore, key, order); 92 | | 93 | * | OrderEventUtils.emitOrderCreated(eventEmitter, key, order); 94 | | 95 | * | return key; 96 | | } 97 | | } 98 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/Market.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title Market 6 | | // @dev Struct for markets 7 | | // 8 | | // Markets support both spot and perp trading, they are created by specifying a 9 | | // long collateral token, short collateral token and index token. 10 | | // 11 | | // Examples: 12 | | // 13 | | // - ETH/USD market with long collateral as ETH, short collateral as a stablecoin, index token as ETH 14 | | // - BTC/USD market with long collateral as WBTC, short collateral as a stablecoin, index token as BTC 15 | | // - SOL/USD market with long collateral as ETH, short collateral as a stablecoin, index token as SOL 16 | | // 17 | | // Liquidity providers can deposit either the long or short collateral token or 18 | | // both to mint liquidity tokens. 19 | | // 20 | | // The long collateral token is used to back long positions, while the short 21 | | // collateral token is used to back short positions. 22 | | // 23 | | // Liquidity providers take on the profits and losses of traders for the market 24 | | // that they provide liquidity for. 25 | | // 26 | | // Having separate markets allows for risk isolation, liquidity providers are 27 | | // only exposed to the markets that they deposit into, this potentially allow 28 | | // for permissionless listings. 29 | | // 30 | | // Traders can use either the long or short token as collateral for the market. 31 | * | library Market { 32 | | // @param marketToken address of the market token for the market 33 | | // @param indexToken address of the index token for the market 34 | | // @param longToken address of the long token for the market 35 | | // @param shortToken address of the short token for the market 36 | | // @param data for any additional data 37 | | struct Props { 38 | | address marketToken; 39 | | address indexToken; 40 | | address longToken; 41 | | address shortToken; 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./MarketPoolValueInfo.sol"; 10 | | 11 | * | library MarketEventUtils { 12 | | using EventUtils for EventUtils.AddressItems; 13 | | using EventUtils for EventUtils.UintItems; 14 | | using EventUtils for EventUtils.IntItems; 15 | | using EventUtils for EventUtils.BoolItems; 16 | | using EventUtils for EventUtils.Bytes32Items; 17 | | using EventUtils for EventUtils.BytesItems; 18 | | using EventUtils for EventUtils.StringItems; 19 | | 20 | | // this event is emitted before a deposit or withdrawal 21 | | // it provides information of the pool state so that the amount 22 | | // of market tokens minted or amount withdrawn from the pool can be checked 23 | * | function emitMarketPoolValueInfo( 24 | | EventEmitter eventEmitter, 25 | | bytes32 tradeKey, 26 | | address market, 27 | | MarketPoolValueInfo.Props memory props, 28 | | uint256 marketTokensSupply 29 | * | ) internal { 30 | * | EventUtils.EventLogData memory eventData; 31 | | 32 | * | eventData.bytes32Items.initItems(1); 33 | * | eventData.bytes32Items.setItem(0, "tradeKey", tradeKey); 34 | | 35 | * | eventData.addressItems.initItems(1); 36 | * | eventData.addressItems.setItem(0, "market", market); 37 | | 38 | * | eventData.intItems.initItems(4); 39 | * | eventData.intItems.setItem(0, "poolValue", props.poolValue); 40 | * | eventData.intItems.setItem(1, "longPnl", props.longPnl); 41 | * | eventData.intItems.setItem(2, "shortPnl", props.shortPnl); 42 | * | eventData.intItems.setItem(3, "netPnl", props.netPnl); 43 | | 44 | * | eventData.uintItems.initItems(8); 45 | * | eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount); 46 | * | eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount); 47 | * | eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd); 48 | * | eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd); 49 | * | eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees); 50 | * | eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor); 51 | * | eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount); 52 | * | eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply); 53 | | 54 | * | eventEmitter.emitEventLog1( 55 | | "MarketPoolValueInfo", 56 | * | Cast.toBytes32(market), 57 | * | eventData 58 | | ); 59 | | } 60 | | 61 | | // this event is emitted after a deposit or withdrawal 62 | | // it provides information of the updated pool state 63 | | // note that the pool state can change even without a deposit / withdrawal 64 | | // e.g. borrowing fees can increase the pool's value with time, trader pnl 65 | | // will change as index prices change 66 | * | function emitMarketPoolValueUpdated( 67 | | EventEmitter eventEmitter, 68 | | bytes32 actionType, 69 | | bytes32 tradeKey, 70 | | address market, 71 | | MarketPoolValueInfo.Props memory props, 72 | | uint256 marketTokensSupply 73 | * | ) internal { 74 | * | EventUtils.EventLogData memory eventData; 75 | | 76 | * | eventData.bytes32Items.initItems(2); 77 | * | eventData.bytes32Items.setItem(0, "actionType", actionType); 78 | * | eventData.bytes32Items.setItem(1, "tradeKey", tradeKey); 79 | | 80 | * | eventData.addressItems.initItems(1); 81 | * | eventData.addressItems.setItem(0, "market", market); 82 | | 83 | * | eventData.intItems.initItems(4); 84 | * | eventData.intItems.setItem(0, "poolValue", props.poolValue); 85 | * | eventData.intItems.setItem(1, "longPnl", props.longPnl); 86 | * | eventData.intItems.setItem(2, "shortPnl", props.shortPnl); 87 | * | eventData.intItems.setItem(3, "netPnl", props.netPnl); 88 | | 89 | * | eventData.uintItems.initItems(8); 90 | * | eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount); 91 | * | eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount); 92 | * | eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd); 93 | * | eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd); 94 | * | eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees); 95 | * | eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor); 96 | * | eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount); 97 | * | eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply); 98 | | 99 | * | eventEmitter.emitEventLog1( 100 | | "MarketPoolValueUpdated", 101 | * | Cast.toBytes32(market), 102 | * | eventData 103 | | ); 104 | | } 105 | | 106 | * | function emitPoolAmountUpdated( 107 | | EventEmitter eventEmitter, 108 | | address market, 109 | | address token, 110 | | int256 delta, 111 | | uint256 nextValue 112 | * | ) internal { 113 | * | EventUtils.EventLogData memory eventData; 114 | | 115 | * | eventData.addressItems.initItems(2); 116 | * | eventData.addressItems.setItem(0, "market", market); 117 | * | eventData.addressItems.setItem(1, "token", token); 118 | | 119 | * | eventData.intItems.initItems(1); 120 | * | eventData.intItems.setItem(0, "delta", delta); 121 | | 122 | * | eventData.uintItems.initItems(1); 123 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 124 | | 125 | * | eventEmitter.emitEventLog1( 126 | | "PoolAmountUpdated", 127 | * | Cast.toBytes32(market), 128 | * | eventData 129 | | ); 130 | | } 131 | | 132 | * | function emitSwapImpactPoolAmountUpdated( 133 | | EventEmitter eventEmitter, 134 | | address market, 135 | | address token, 136 | | int256 delta, 137 | | uint256 nextValue 138 | * | ) internal { 139 | * | EventUtils.EventLogData memory eventData; 140 | | 141 | * | eventData.addressItems.initItems(2); 142 | * | eventData.addressItems.setItem(0, "market", market); 143 | * | eventData.addressItems.setItem(1, "token", token); 144 | | 145 | * | eventData.intItems.initItems(1); 146 | * | eventData.intItems.setItem(0, "delta", delta); 147 | | 148 | * | eventData.uintItems.initItems(1); 149 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 150 | | 151 | * | eventEmitter.emitEventLog1( 152 | | "SwapImpactPoolAmountUpdated", 153 | * | Cast.toBytes32(market), 154 | * | eventData 155 | | ); 156 | | } 157 | | 158 | | function emitPositionImpactPoolDistributed( 159 | | EventEmitter eventEmitter, 160 | | address market, 161 | | uint256 distributionAmount, 162 | | uint256 nextPositionImpactPoolAmount 163 | | ) internal { 164 | | EventUtils.EventLogData memory eventData; 165 | | 166 | | eventData.addressItems.initItems(1); 167 | | eventData.addressItems.setItem(0, "market", market); 168 | | 169 | | eventData.uintItems.initItems(2); 170 | | eventData.uintItems.setItem(0, "distributionAmount", distributionAmount); 171 | | eventData.uintItems.setItem(1, "nextPositionImpactPoolAmount", nextPositionImpactPoolAmount); 172 | | 173 | | eventEmitter.emitEventLog1( 174 | | "PositionImpactPoolDistributed", 175 | | Cast.toBytes32(market), 176 | | eventData 177 | | ); 178 | | } 179 | | 180 | * | function emitPositionImpactPoolAmountUpdated( 181 | | EventEmitter eventEmitter, 182 | | address market, 183 | | int256 delta, 184 | | uint256 nextValue 185 | * | ) internal { 186 | * | EventUtils.EventLogData memory eventData; 187 | | 188 | * | eventData.addressItems.initItems(1); 189 | * | eventData.addressItems.setItem(0, "market", market); 190 | | 191 | * | eventData.intItems.initItems(1); 192 | * | eventData.intItems.setItem(0, "delta", delta); 193 | | 194 | * | eventData.uintItems.initItems(1); 195 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 196 | | 197 | * | eventEmitter.emitEventLog1( 198 | | "PositionImpactPoolAmountUpdated", 199 | * | Cast.toBytes32(market), 200 | * | eventData 201 | | ); 202 | | } 203 | | 204 | * | function emitOpenInterestUpdated( 205 | | EventEmitter eventEmitter, 206 | | address market, 207 | | address collateralToken, 208 | | bool isLong, 209 | | int256 delta, 210 | | uint256 nextValue 211 | * | ) internal { 212 | * | EventUtils.EventLogData memory eventData; 213 | | 214 | * | eventData.addressItems.initItems(2); 215 | * | eventData.addressItems.setItem(0, "market", market); 216 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 217 | | 218 | * | eventData.boolItems.initItems(1); 219 | * | eventData.boolItems.setItem(0, "isLong", isLong); 220 | | 221 | * | eventData.intItems.initItems(1); 222 | * | eventData.intItems.setItem(0, "delta", delta); 223 | | 224 | * | eventData.uintItems.initItems(1); 225 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 226 | | 227 | * | eventEmitter.emitEventLog1( 228 | | "OpenInterestUpdated", 229 | * | Cast.toBytes32(market), 230 | * | eventData 231 | | ); 232 | | } 233 | | 234 | | function emitVirtualSwapInventoryUpdated( 235 | | EventEmitter eventEmitter, 236 | | address market, 237 | | bool isLongToken, 238 | | bytes32 virtualMarketId, 239 | | int256 delta, 240 | | uint256 nextValue 241 | | ) internal { 242 | | EventUtils.EventLogData memory eventData; 243 | | 244 | | eventData.addressItems.initItems(1); 245 | | eventData.addressItems.setItem(0, "market", market); 246 | | 247 | | eventData.boolItems.initItems(1); 248 | | eventData.boolItems.setItem(0, "isLongToken", isLongToken); 249 | | 250 | | eventData.bytes32Items.initItems(1); 251 | | eventData.bytes32Items.setItem(0, "virtualMarketId", virtualMarketId); 252 | | 253 | | eventData.intItems.initItems(1); 254 | | eventData.intItems.setItem(0, "delta", delta); 255 | | 256 | | eventData.uintItems.initItems(1); 257 | | eventData.uintItems.setItem(0, "nextValue", nextValue); 258 | | 259 | | eventEmitter.emitEventLog2( 260 | | "VirtualSwapInventoryUpdated", 261 | | Cast.toBytes32(market), 262 | | virtualMarketId, 263 | | eventData 264 | | ); 265 | | } 266 | | 267 | | function emitVirtualPositionInventoryUpdated( 268 | | EventEmitter eventEmitter, 269 | | address token, 270 | | bytes32 virtualTokenId, 271 | | int256 delta, 272 | | int256 nextValue 273 | | ) internal { 274 | | EventUtils.EventLogData memory eventData; 275 | | 276 | | eventData.addressItems.initItems(1); 277 | | eventData.addressItems.setItem(0, "token", token); 278 | | 279 | | eventData.bytes32Items.initItems(1); 280 | | eventData.bytes32Items.setItem(0, "virtualTokenId", virtualTokenId); 281 | | 282 | | eventData.intItems.initItems(2); 283 | | eventData.intItems.setItem(0, "delta", delta); 284 | | eventData.intItems.setItem(1, "nextValue", nextValue); 285 | | 286 | | eventEmitter.emitEventLog2( 287 | | "VirtualPositionInventoryUpdated", 288 | | Cast.toBytes32(token), 289 | | virtualTokenId, 290 | | eventData 291 | | ); 292 | | } 293 | | 294 | * | function emitOpenInterestInTokensUpdated( 295 | | EventEmitter eventEmitter, 296 | | address market, 297 | | address collateralToken, 298 | | bool isLong, 299 | | int256 delta, 300 | | uint256 nextValue 301 | * | ) internal { 302 | * | EventUtils.EventLogData memory eventData; 303 | | 304 | * | eventData.addressItems.initItems(2); 305 | * | eventData.addressItems.setItem(0, "market", market); 306 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 307 | | 308 | * | eventData.boolItems.initItems(1); 309 | * | eventData.boolItems.setItem(0, "isLong", isLong); 310 | | 311 | * | eventData.intItems.initItems(1); 312 | * | eventData.intItems.setItem(0, "delta", delta); 313 | | 314 | * | eventData.uintItems.initItems(1); 315 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 316 | | 317 | * | eventEmitter.emitEventLog1( 318 | | "OpenInterestInTokensUpdated", 319 | * | Cast.toBytes32(market), 320 | * | eventData 321 | | ); 322 | | } 323 | | 324 | * | function emitCollateralSumUpdated( 325 | | EventEmitter eventEmitter, 326 | | address market, 327 | | address collateralToken, 328 | | bool isLong, 329 | | int256 delta, 330 | | uint256 nextValue 331 | * | ) internal { 332 | * | EventUtils.EventLogData memory eventData; 333 | | 334 | * | eventData.addressItems.initItems(2); 335 | * | eventData.addressItems.setItem(0, "market", market); 336 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 337 | | 338 | * | eventData.boolItems.initItems(1); 339 | * | eventData.boolItems.setItem(0, "isLong", isLong); 340 | | 341 | * | eventData.intItems.initItems(1); 342 | * | eventData.intItems.setItem(0, "delta", delta); 343 | | 344 | * | eventData.uintItems.initItems(1); 345 | * | eventData.uintItems.setItem(0, "nextValue", nextValue); 346 | | 347 | * | eventEmitter.emitEventLog1( 348 | | "CollateralSumUpdated", 349 | * | Cast.toBytes32(market), 350 | * | eventData 351 | | ); 352 | | } 353 | | 354 | * | function emitBorrowingFactorUpdated( 355 | | EventEmitter eventEmitter, 356 | | address market, 357 | | bool isLong, 358 | | uint256 delta, 359 | | uint256 nextValue 360 | * | ) internal { 361 | * | EventUtils.EventLogData memory eventData; 362 | | 363 | * | eventData.addressItems.initItems(1); 364 | * | eventData.addressItems.setItem(0, "market", market); 365 | | 366 | * | eventData.boolItems.initItems(1); 367 | * | eventData.boolItems.setItem(0, "isLong", isLong); 368 | | 369 | * | eventData.uintItems.initItems(2); 370 | * | eventData.uintItems.setItem(0, "delta", delta); 371 | * | eventData.uintItems.setItem(1, "nextValue", nextValue); 372 | | 373 | * | eventEmitter.emitEventLog1( 374 | | "CumulativeBorrowingFactorUpdated", 375 | * | Cast.toBytes32(market), 376 | * | eventData 377 | | ); 378 | | } 379 | | 380 | * | function emitFundingFeeAmountPerSizeUpdated( 381 | | EventEmitter eventEmitter, 382 | | address market, 383 | | address collateralToken, 384 | | bool isLong, 385 | | uint256 delta, 386 | | uint256 value 387 | * | ) internal { 388 | * | EventUtils.EventLogData memory eventData; 389 | | 390 | * | eventData.addressItems.initItems(2); 391 | * | eventData.addressItems.setItem(0, "market", market); 392 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 393 | | 394 | * | eventData.boolItems.initItems(1); 395 | * | eventData.boolItems.setItem(0, "isLong", isLong); 396 | | 397 | * | eventData.uintItems.initItems(2); 398 | * | eventData.uintItems.setItem(0, "delta", delta); 399 | * | eventData.uintItems.setItem(1, "value", value); 400 | | 401 | * | eventEmitter.emitEventLog1( 402 | | "FundingFeeAmountPerSizeUpdated", 403 | * | Cast.toBytes32(market), 404 | * | eventData 405 | | ); 406 | | } 407 | | 408 | * | function emitClaimableFundingAmountPerSizeUpdated( 409 | | EventEmitter eventEmitter, 410 | | address market, 411 | | address collateralToken, 412 | | bool isLong, 413 | | uint256 delta, 414 | | uint256 value 415 | * | ) internal { 416 | * | EventUtils.EventLogData memory eventData; 417 | | 418 | * | eventData.addressItems.initItems(2); 419 | * | eventData.addressItems.setItem(0, "market", market); 420 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 421 | | 422 | * | eventData.boolItems.initItems(1); 423 | * | eventData.boolItems.setItem(0, "isLong", isLong); 424 | | 425 | * | eventData.uintItems.initItems(2); 426 | * | eventData.uintItems.setItem(0, "delta", delta); 427 | * | eventData.uintItems.setItem(1, "value", value); 428 | | 429 | * | eventEmitter.emitEventLog1( 430 | | "ClaimableFundingAmountPerSizeUpdated", 431 | * | Cast.toBytes32(market), 432 | * | eventData 433 | | ); 434 | | } 435 | | 436 | * | function emitClaimableFundingUpdated( 437 | | EventEmitter eventEmitter, 438 | | address market, 439 | | address token, 440 | | address account, 441 | | uint256 delta, 442 | | uint256 nextValue, 443 | | uint256 nextPoolValue 444 | * | ) internal { 445 | * | EventUtils.EventLogData memory eventData; 446 | | 447 | * | eventData.addressItems.initItems(3); 448 | * | eventData.addressItems.setItem(0, "market", market); 449 | * | eventData.addressItems.setItem(1, "token", token); 450 | * | eventData.addressItems.setItem(2, "account", account); 451 | | 452 | * | eventData.uintItems.initItems(3); 453 | * | eventData.uintItems.setItem(0, "delta", delta); 454 | * | eventData.uintItems.setItem(1, "nextValue", nextValue); 455 | * | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue); 456 | | 457 | * | eventEmitter.emitEventLog1( 458 | | "ClaimableFundingUpdated", 459 | * | Cast.toBytes32(account), 460 | * | eventData 461 | | ); 462 | | } 463 | | 464 | * | function emitFundingFeesClaimed( 465 | | EventEmitter eventEmitter, 466 | | address market, 467 | | address token, 468 | | address account, 469 | | address receiver, 470 | | uint256 amount, 471 | | uint256 nextPoolValue 472 | * | ) internal { 473 | * | EventUtils.EventLogData memory eventData; 474 | | 475 | * | eventData.addressItems.initItems(4); 476 | * | eventData.addressItems.setItem(0, "market", market); 477 | * | eventData.addressItems.setItem(1, "token", token); 478 | * | eventData.addressItems.setItem(2, "account", account); 479 | * | eventData.addressItems.setItem(3, "receiver", receiver); 480 | | 481 | * | eventData.uintItems.initItems(2); 482 | * | eventData.uintItems.setItem(0, "amount", amount); 483 | * | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue); 484 | | 485 | * | eventEmitter.emitEventLog1( 486 | | "FundingFeesClaimed", 487 | * | Cast.toBytes32(account), 488 | * | eventData 489 | | ); 490 | | } 491 | | 492 | | function emitClaimableFundingUpdated( 493 | | EventEmitter eventEmitter, 494 | | address market, 495 | | address token, 496 | | uint256 timeKey, 497 | | address account, 498 | | uint256 delta, 499 | | uint256 nextValue 500 | | ) internal { 501 | | EventUtils.EventLogData memory eventData; 502 | | 503 | | eventData.addressItems.initItems(3); 504 | | eventData.addressItems.setItem(0, "market", market); 505 | | eventData.addressItems.setItem(1, "token", token); 506 | | eventData.addressItems.setItem(2, "account", account); 507 | | 508 | | eventData.uintItems.initItems(3); 509 | | eventData.uintItems.setItem(0, "timeKey", timeKey); 510 | | eventData.uintItems.setItem(1, "delta", delta); 511 | | eventData.uintItems.setItem(2, "nextValue", nextValue); 512 | | 513 | | eventEmitter.emitEventLog1( 514 | | "ClaimableFundingUpdated", 515 | | Cast.toBytes32(account), 516 | | eventData 517 | | ); 518 | | } 519 | | 520 | | function emitClaimableCollateralUpdated( 521 | | EventEmitter eventEmitter, 522 | | address market, 523 | | address token, 524 | | uint256 timeKey, 525 | | address account, 526 | | uint256 delta, 527 | | uint256 nextValue, 528 | | uint256 nextPoolValue 529 | | ) internal { 530 | | EventUtils.EventLogData memory eventData; 531 | | 532 | | eventData.addressItems.initItems(3); 533 | | eventData.addressItems.setItem(0, "market", market); 534 | | eventData.addressItems.setItem(1, "token", token); 535 | | eventData.addressItems.setItem(2, "account", account); 536 | | 537 | | eventData.uintItems.initItems(4); 538 | | eventData.uintItems.setItem(0, "timeKey", timeKey); 539 | | eventData.uintItems.setItem(1, "delta", delta); 540 | | eventData.uintItems.setItem(2, "nextValue", nextValue); 541 | | eventData.uintItems.setItem(3, "nextPoolValue", nextPoolValue); 542 | | 543 | | eventEmitter.emitEventLog1( 544 | | "ClaimableCollateralUpdated", 545 | | Cast.toBytes32(account), 546 | | eventData 547 | | ); 548 | | } 549 | | 550 | | function emitCollateralClaimed( 551 | | EventEmitter eventEmitter, 552 | | address market, 553 | | address token, 554 | | uint256 timeKey, 555 | | address account, 556 | | address receiver, 557 | | uint256 amount, 558 | | uint256 nextPoolValue 559 | | ) internal { 560 | | EventUtils.EventLogData memory eventData; 561 | | 562 | | eventData.addressItems.initItems(4); 563 | | eventData.addressItems.setItem(0, "market", market); 564 | | eventData.addressItems.setItem(1, "token", token); 565 | | eventData.addressItems.setItem(2, "account", account); 566 | | eventData.addressItems.setItem(3, "receiver", receiver); 567 | | 568 | | eventData.uintItems.initItems(3); 569 | | eventData.uintItems.setItem(0, "timeKey", timeKey); 570 | | eventData.uintItems.setItem(1, "amount", amount); 571 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue); 572 | | 573 | | eventEmitter.emitEventLog1( 574 | | "CollateralClaimed", 575 | | Cast.toBytes32(account), 576 | | eventData 577 | | ); 578 | | } 579 | | 580 | | function emitUiFeeFactorUpdated( 581 | | EventEmitter eventEmitter, 582 | | address account, 583 | | uint256 uiFeeFactor 584 | | ) internal { 585 | | 586 | | EventUtils.EventLogData memory eventData; 587 | | 588 | | eventData.addressItems.initItems(1); 589 | | eventData.addressItems.setItem(0, "account", account); 590 | | 591 | | eventData.uintItems.initItems(1); 592 | | eventData.uintItems.setItem(0, "uiFeeFactor", uiFeeFactor); 593 | | 594 | | eventEmitter.emitEventLog1( 595 | | "UiFeeFactorUpdated", 596 | | Cast.toBytes32(account), 597 | | eventData 598 | | ); 599 | | } 600 | | } 601 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketFactory.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./MarketToken.sol"; 6 | | import "./Market.sol"; 7 | | import "./MarketStoreUtils.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | import "../utils/Cast.sol"; 10 | | 11 | | // @title MarketFactory 12 | | // @dev Contract to create markets 13 | * | contract MarketFactory is RoleModule { 14 | | using Market for Market.Props; 15 | | 16 | | using EventUtils for EventUtils.AddressItems; 17 | | using EventUtils for EventUtils.UintItems; 18 | | using EventUtils for EventUtils.IntItems; 19 | | using EventUtils for EventUtils.BoolItems; 20 | | using EventUtils for EventUtils.Bytes32Items; 21 | | using EventUtils for EventUtils.BytesItems; 22 | | using EventUtils for EventUtils.StringItems; 23 | | 24 | | DataStore public immutable dataStore; 25 | | EventEmitter public immutable eventEmitter; 26 | | 27 | | constructor( 28 | | RoleStore _roleStore, 29 | | DataStore _dataStore, 30 | | EventEmitter _eventEmitter 31 | | ) RoleModule(_roleStore) { 32 | | dataStore = _dataStore; 33 | | eventEmitter = _eventEmitter; 34 | | } 35 | | 36 | | // @dev creates a market 37 | | // @param indexToken address of the index token for the market 38 | | // @param longToken address of the long token for the market 39 | | // @param shortToken address of the short token for the market 40 | | // @param marketType the type of the market 41 | | function createMarket( 42 | | address indexToken, 43 | | address longToken, 44 | | address shortToken, 45 | | bytes32 marketType 46 | | ) external onlyMarketKeeper returns (Market.Props memory) { 47 | | bytes32 salt = keccak256(abi.encode( 48 | | "GMX_MARKET", 49 | | indexToken, 50 | | longToken, 51 | | shortToken, 52 | | marketType 53 | | )); 54 | | 55 | | address existingMarketAddress = dataStore.getAddress(MarketStoreUtils.getMarketSaltHash(salt)); 56 | | if (existingMarketAddress != address(0)) { 57 | | revert Errors.MarketAlreadyExists(salt, existingMarketAddress); 58 | | } 59 | | 60 | | MarketToken marketToken = new MarketToken{salt: salt}(roleStore, dataStore); 61 | | 62 | | // the marketType is not stored with the market, it is mainly used to ensure 63 | | // markets with the same indexToken, longToken and shortToken can be created if needed 64 | | Market.Props memory market = Market.Props( 65 | | address(marketToken), 66 | | indexToken, 67 | | longToken, 68 | | shortToken 69 | | ); 70 | | 71 | | MarketStoreUtils.set(dataStore, address(marketToken), salt, market); 72 | | 73 | | emitMarketCreated(address(marketToken), salt, indexToken, longToken, shortToken); 74 | | 75 | | return market; 76 | | } 77 | | 78 | | function emitMarketCreated( 79 | | address marketToken, 80 | | bytes32 salt, 81 | | address indexToken, 82 | | address longToken, 83 | | address shortToken 84 | | ) internal { 85 | | EventUtils.EventLogData memory eventData; 86 | | 87 | | eventData.addressItems.initItems(4); 88 | | eventData.addressItems.setItem(0, "marketToken", marketToken); 89 | | eventData.addressItems.setItem(1, "indexToken", indexToken); 90 | | eventData.addressItems.setItem(2, "longToken", longToken); 91 | | eventData.addressItems.setItem(3, "shortToken", shortToken); 92 | | 93 | | eventData.bytes32Items.initItems(1); 94 | | eventData.bytes32Items.setItem(0, "salt", salt); 95 | | 96 | | eventEmitter.emitEventLog1( 97 | | "MarketCreated", 98 | | Cast.toBytes32(marketToken), 99 | | eventData 100 | | ); 101 | | } 102 | | } 103 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketPoolValueInfo.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title MarketPoolInfo 6 | * | library MarketPoolValueInfo { 7 | | // @dev struct to avoid stack too deep errors for the getPoolValue call 8 | | // @param value the pool value 9 | | // @param longTokenAmount the amount of long token in the pool 10 | | // @param shortTokenAmount the amount of short token in the pool 11 | | // @param longTokenUsd the USD value of the long tokens in the pool 12 | | // @param shortTokenUsd the USD value of the short tokens in the pool 13 | | // @param totalBorrowingFees the total pending borrowing fees for the market 14 | | // @param borrowingFeePoolFactor the pool factor for borrowing fees 15 | | // @param impactPoolAmount the amount of tokens in the impact pool 16 | | // @param longPnl the pending pnl of long positions 17 | | // @param shortPnl the pending pnl of short positions 18 | | // @param netPnl the net pnl of long and short positions 19 | | struct Props { 20 | | int256 poolValue; 21 | | int256 longPnl; 22 | | int256 shortPnl; 23 | | int256 netPnl; 24 | | 25 | | uint256 longTokenAmount; 26 | | uint256 shortTokenAmount; 27 | | uint256 longTokenUsd; 28 | | uint256 shortTokenUsd; 29 | | 30 | | uint256 totalBorrowingFees; 31 | | uint256 borrowingFeePoolFactor; 32 | | 33 | | uint256 impactPoolAmount; 34 | | } 35 | | } 36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Market.sol"; 9 | | 10 | | /** 11 | | * @title MarketStoreUtils 12 | | * @dev Library for market storage functions 13 | | */ 14 | * | library MarketStoreUtils { 15 | | using Market for Market.Props; 16 | | 17 | | bytes32 internal constant MARKET_SALT = keccak256(abi.encode("MARKET_SALT")); 18 | | bytes32 internal constant MARKET_KEY = keccak256(abi.encode("MARKET_KEY")); 19 | * | bytes32 internal constant MARKET_TOKEN = keccak256(abi.encode("MARKET_TOKEN")); 20 | * | bytes32 internal constant INDEX_TOKEN = keccak256(abi.encode("INDEX_TOKEN")); 21 | * | bytes32 internal constant LONG_TOKEN = keccak256(abi.encode("LONG_TOKEN")); 22 | * | bytes32 internal constant SHORT_TOKEN = keccak256(abi.encode("SHORT_TOKEN")); 23 | | 24 | * | function get(DataStore dataStore, address key) internal view returns (Market.Props memory) { 25 | * | Market.Props memory market; 26 | * | if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) { 27 | * | return market; 28 | | } 29 | | 30 | * | market.marketToken = dataStore.getAddress( 31 | * | keccak256(abi.encode(key, MARKET_TOKEN)) 32 | | ); 33 | | 34 | * | market.indexToken = dataStore.getAddress( 35 | * | keccak256(abi.encode(key, INDEX_TOKEN)) 36 | | ); 37 | | 38 | * | market.longToken = dataStore.getAddress( 39 | * | keccak256(abi.encode(key, LONG_TOKEN)) 40 | | ); 41 | | 42 | * | market.shortToken = dataStore.getAddress( 43 | * | keccak256(abi.encode(key, SHORT_TOKEN)) 44 | | ); 45 | | 46 | * | return market; 47 | | } 48 | | 49 | | function getBySalt(DataStore dataStore, bytes32 salt) internal view returns (Market.Props memory) { 50 | | address key = dataStore.getAddress(getMarketSaltHash(salt)); 51 | | return get(dataStore, key); 52 | | } 53 | | 54 | | function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) internal { 55 | | dataStore.addAddress( 56 | | Keys.MARKET_LIST, 57 | | key 58 | | ); 59 | | 60 | | // the salt is based on the market props while the key gives the market's address 61 | | // use the salt to store a reference to the key to allow the key to be retrieved 62 | | // using just the salt value 63 | | dataStore.setAddress( 64 | | getMarketSaltHash(salt), 65 | | key 66 | | ); 67 | | 68 | | dataStore.setAddress( 69 | | keccak256(abi.encode(key, MARKET_TOKEN)), 70 | | market.marketToken 71 | | ); 72 | | 73 | | dataStore.setAddress( 74 | | keccak256(abi.encode(key, INDEX_TOKEN)), 75 | | market.indexToken 76 | | ); 77 | | 78 | | dataStore.setAddress( 79 | | keccak256(abi.encode(key, LONG_TOKEN)), 80 | | market.longToken 81 | | ); 82 | | 83 | | dataStore.setAddress( 84 | | keccak256(abi.encode(key, SHORT_TOKEN)), 85 | | market.shortToken 86 | | ); 87 | | } 88 | | 89 | | function remove(DataStore dataStore, address key) internal { 90 | | if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) { 91 | | revert Errors.MarketNotFound(key); 92 | | } 93 | | 94 | | dataStore.removeAddress( 95 | | Keys.MARKET_LIST, 96 | | key 97 | | ); 98 | | 99 | | dataStore.removeAddress( 100 | | keccak256(abi.encode(key, MARKET_TOKEN)) 101 | | ); 102 | | 103 | | dataStore.removeAddress( 104 | | keccak256(abi.encode(key, INDEX_TOKEN)) 105 | | ); 106 | | 107 | | dataStore.removeAddress( 108 | | keccak256(abi.encode(key, LONG_TOKEN)) 109 | | ); 110 | | 111 | | dataStore.removeAddress( 112 | | keccak256(abi.encode(key, SHORT_TOKEN)) 113 | | ); 114 | | } 115 | | 116 | | function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) { 117 | | return keccak256(abi.encode(MARKET_SALT, salt)); 118 | | } 119 | | 120 | | function getMarketCount(DataStore dataStore) internal view returns (uint256) { 121 | | return dataStore.getAddressCount(Keys.MARKET_LIST); 122 | | } 123 | | 124 | | function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) { 125 | | return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end); 126 | | } 127 | | } 128 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketToken.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | | import "../bank/Bank.sol"; 7 | | 8 | | // @title MarketToken 9 | | // @dev The market token for a market, stores funds for the market and keeps track 10 | | // of the liquidity owners 11 | * | contract MarketToken is ERC20, Bank { 12 | | constructor(RoleStore _roleStore, DataStore _dataStore) ERC20("GMX Market", "GM") Bank(_roleStore, _dataStore) { 13 | | } 14 | | 15 | | // @dev mint market tokens to an account 16 | | // @param account the account to mint to 17 | | // @param amount the amount of tokens to mint 18 | * | function mint(address account, uint256 amount) external onlyController { 19 | * | _mint(account, amount); 20 | | } 21 | | 22 | | // @dev burn market tokens from an account 23 | | // @param account the account to burn tokens for 24 | | // @param amount the amount of tokens to burn 25 | * | function burn(address account, uint256 amount) external onlyController { 26 | * | _burn(account, amount); 27 | | } 28 | | } 29 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/market/MarketUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | import "../bank/StrictBank.sol"; 10 | | 11 | | import "./Market.sol"; 12 | | import "./MarketPoolValueInfo.sol"; 13 | | import "./MarketToken.sol"; 14 | | import "./MarketEventUtils.sol"; 15 | | import "./MarketStoreUtils.sol"; 16 | | 17 | | import "../position/Position.sol"; 18 | | import "../order/Order.sol"; 19 | | 20 | | import "../oracle/Oracle.sol"; 21 | | import "../price/Price.sol"; 22 | | 23 | | import "../utils/Calc.sol"; 24 | | import "../utils/Precision.sol"; 25 | | import {console} from "lib/forge-std/src/Test.sol"; 26 | | 27 | | // @title MarketUtils 28 | | // @dev Library for market functions 29 | * | library MarketUtils { 30 | | using SignedMath for int256; 31 | | using SafeCast for int256; 32 | | using SafeCast for uint256; 33 | | 34 | | using Market for Market.Props; 35 | | using Position for Position.Props; 36 | | using Order for Order.Props; 37 | | using Price for Price.Props; 38 | | 39 | | enum FundingRateChangeType { 40 | | NoChange, 41 | | Increase, 42 | | Decrease 43 | | } 44 | | 45 | | // @dev struct to store the prices of tokens of a market 46 | | // @param indexTokenPrice price of the market's index token 47 | | // @param longTokenPrice price of the market's long token 48 | | // @param shortTokenPrice price of the market's short token 49 | | struct MarketPrices { 50 | | Price.Props indexTokenPrice; 51 | | Price.Props longTokenPrice; 52 | | Price.Props shortTokenPrice; 53 | | } 54 | | 55 | | struct CollateralType { 56 | | uint256 longToken; 57 | | uint256 shortToken; 58 | | } 59 | | 60 | | struct PositionType { 61 | | CollateralType long; 62 | | CollateralType short; 63 | | } 64 | | 65 | | // @dev struct for the result of the getNextFundingAmountPerSize call 66 | | // note that abs(nextSavedFundingFactorPerSecond) may not equal the fundingFactorPerSecond 67 | | // see getNextFundingFactorPerSecond for more info 68 | | struct GetNextFundingAmountPerSizeResult { 69 | | bool longsPayShorts; 70 | | uint256 fundingFactorPerSecond; 71 | | int256 nextSavedFundingFactorPerSecond; 72 | | PositionType fundingFeeAmountPerSizeDelta; 73 | | PositionType claimableFundingAmountPerSizeDelta; 74 | | } 75 | | 76 | | struct GetNextFundingAmountPerSizeCache { 77 | | PositionType openInterest; 78 | | uint256 longOpenInterest; 79 | | uint256 shortOpenInterest; 80 | | uint256 durationInSeconds; 81 | | uint256 sizeOfLargerSide; 82 | | uint256 fundingUsd; 83 | | uint256 fundingUsdForLongCollateral; 84 | | uint256 fundingUsdForShortCollateral; 85 | | } 86 | | 87 | | struct GetNextFundingFactorPerSecondCache { 88 | | uint256 diffUsd; 89 | | uint256 totalOpenInterest; 90 | | uint256 fundingFactor; 91 | | uint256 fundingExponentFactor; 92 | | uint256 diffUsdAfterExponent; 93 | | uint256 diffUsdToOpenInterestFactor; 94 | | int256 savedFundingFactorPerSecond; 95 | | uint256 savedFundingFactorPerSecondMagnitude; 96 | | int256 nextSavedFundingFactorPerSecond; 97 | | int256 nextSavedFundingFactorPerSecondWithMinBound; 98 | | } 99 | | 100 | | struct FundingConfigCache { 101 | | uint256 thresholdForStableFunding; 102 | | uint256 thresholdForDecreaseFunding; 103 | | uint256 fundingIncreaseFactorPerSecond; 104 | | uint256 fundingDecreaseFactorPerSecond; 105 | | uint256 minFundingFactorPerSecond; 106 | | uint256 maxFundingFactorPerSecond; 107 | | } 108 | | 109 | | struct GetExpectedMinTokenBalanceCache { 110 | | uint256 poolAmount; 111 | | uint256 swapImpactPoolAmount; 112 | | uint256 claimableCollateralAmount; 113 | | uint256 claimableFeeAmount; 114 | | uint256 claimableUiFeeAmount; 115 | | uint256 affiliateRewardAmount; 116 | | } 117 | | 118 | | // @dev get the market token's price 119 | | // @param dataStore DataStore 120 | | // @param market the market to check 121 | | // @param longTokenPrice the price of the long token 122 | | // @param shortTokenPrice the price of the short token 123 | | // @param indexTokenPrice the price of the index token 124 | | // @param maximize whether to maximize or minimize the market token price 125 | | // @return returns (the market token's price, MarketPoolValueInfo.Props) 126 | | function getMarketTokenPrice( 127 | | DataStore dataStore, 128 | | Market.Props memory market, 129 | | Price.Props memory indexTokenPrice, 130 | | Price.Props memory longTokenPrice, 131 | | Price.Props memory shortTokenPrice, 132 | | bytes32 pnlFactorType, 133 | | bool maximize 134 | | ) internal view returns (int256, MarketPoolValueInfo.Props memory) { 135 | | uint256 supply = getMarketTokenSupply( 136 | | MarketToken(payable(market.marketToken)) 137 | | ); 138 | | 139 | | MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo( 140 | | dataStore, 141 | | market, 142 | | indexTokenPrice, 143 | | longTokenPrice, 144 | | shortTokenPrice, 145 | | pnlFactorType, 146 | | maximize 147 | | ); 148 | | 149 | | // if the supply is zero then treat the market token price as 1 USD 150 | | if (supply == 0) { 151 | | return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo); 152 | | } 153 | | 154 | | if (poolValueInfo.poolValue == 0) { 155 | | return (0, poolValueInfo); 156 | | } 157 | | 158 | | int256 marketTokenPrice = Precision.mulDiv( 159 | | Precision.WEI_PRECISION, 160 | | poolValueInfo.poolValue, 161 | | supply 162 | | ); 163 | | return (marketTokenPrice, poolValueInfo); 164 | | } 165 | | 166 | | // @dev get the total supply of the marketToken 167 | | // @param marketToken the marketToken 168 | | // @return the total supply of the marketToken 169 | * | function getMarketTokenSupply( 170 | | MarketToken marketToken 171 | * | ) internal view returns (uint256) { 172 | * | return marketToken.totalSupply(); 173 | | } 174 | | 175 | | // @dev get the opposite token of the market 176 | | // if the inputToken is the longToken return the shortToken and vice versa 177 | | // @param inputToken the input token 178 | | // @param market the market values 179 | | // @return the opposite token 180 | * | function getOppositeToken( 181 | | address inputToken, 182 | | Market.Props memory market 183 | * | ) internal pure returns (address) { 184 | * | if (inputToken == market.longToken) { 185 | * | return market.shortToken; 186 | | } 187 | | 188 | * | if (inputToken == market.shortToken) { 189 | * | return market.longToken; 190 | | } 191 | | 192 | | revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken); 193 | | } 194 | | 195 | * | function validateSwapMarket( 196 | | DataStore dataStore, 197 | | address marketAddress 198 | * | ) internal view { 199 | * | Market.Props memory market = MarketStoreUtils.get( 200 | * | dataStore, 201 | * | marketAddress 202 | | ); 203 | * | validateSwapMarket(dataStore, market); 204 | | } 205 | | 206 | * | function validateSwapMarket( 207 | | DataStore dataStore, 208 | | Market.Props memory market 209 | | ) internal view { 210 | * | validateEnabledMarket(dataStore, market); 211 | | 212 | * | if (market.longToken == market.shortToken) { 213 | | revert Errors.InvalidSwapMarket(market.marketToken); 214 | | } 215 | | } 216 | | 217 | | // @dev get the token price from the stored MarketPrices 218 | | // @param token the token to get the price for 219 | | // @param the market values 220 | | // @param the market token prices 221 | | // @return the token price from the stored MarketPrices 222 | * | function getCachedTokenPrice( 223 | | address token, 224 | | Market.Props memory market, 225 | | MarketPrices memory prices 226 | * | ) internal pure returns (Price.Props memory) { 227 | * | if (token == market.longToken) { 228 | * | return prices.longTokenPrice; 229 | | } 230 | * | if (token == market.shortToken) { 231 | * | return prices.shortTokenPrice; 232 | | } 233 | | if (token == market.indexToken) { 234 | | return prices.indexTokenPrice; 235 | | } 236 | | 237 | | revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken); 238 | | } 239 | | 240 | | // @dev return the primary prices for the market tokens 241 | | // @param oracle Oracle 242 | | // @param market the market values 243 | * | function getMarketPrices( 244 | | Oracle oracle, 245 | | Market.Props memory market 246 | * | ) internal view returns (MarketPrices memory) { 247 | * | return 248 | * | MarketPrices( 249 | * | oracle.getPrimaryPrice(market.indexToken), 250 | * | oracle.getPrimaryPrice(market.longToken), 251 | * | oracle.getPrimaryPrice(market.shortToken) 252 | | ); 253 | | } 254 | | 255 | | // @dev get the usd value of either the long or short tokens in the pool 256 | | // without accounting for the pnl of open positions 257 | | // @param dataStore DataStore 258 | | // @param market the market values 259 | | // @param prices the prices of the market tokens 260 | | // @param whether to return the value for the long or short token 261 | | // @return the usd value of either the long or short tokens in the pool 262 | * | function getPoolUsdWithoutPnl( 263 | | DataStore dataStore, 264 | | Market.Props memory market, 265 | | MarketPrices memory prices, 266 | | bool isLong, 267 | | bool maximize 268 | * | ) internal view returns (uint256) { 269 | * | address token = isLong ? market.longToken : market.shortToken; 270 | | // note that if it is a single token market, the poolAmount returned will be 271 | | // the amount of tokens in the pool divided by 2 272 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token); 273 | * | uint256 tokenPrice; 274 | | 275 | * | if (maximize) { 276 | | tokenPrice = isLong 277 | | ? prices.longTokenPrice.max 278 | | : prices.shortTokenPrice.max; 279 | | } else { 280 | * | tokenPrice = isLong 281 | * | ? prices.longTokenPrice.min 282 | * | : prices.shortTokenPrice.min; 283 | | } 284 | | 285 | * | return poolAmount * tokenPrice; 286 | | } 287 | | 288 | | // @dev get the USD value of a pool 289 | | // the value of a pool is the worth of the liquidity provider tokens in the pool - pending trader pnl 290 | | // we use the token index prices to calculate this and ignore price impact since if all positions were closed the 291 | | // net price impact should be zero 292 | | // @param dataStore DataStore 293 | | // @param market the market values 294 | | // @param longTokenPrice price of the long token 295 | | // @param shortTokenPrice price of the short token 296 | | // @param indexTokenPrice price of the index token 297 | | // @param maximize whether to maximize or minimize the pool value 298 | | // @return the value information of a pool 299 | * | function getPoolValueInfo( 300 | | DataStore dataStore, 301 | | Market.Props memory market, 302 | | Price.Props memory indexTokenPrice, 303 | | Price.Props memory longTokenPrice, 304 | | Price.Props memory shortTokenPrice, 305 | | bytes32 pnlFactorType, 306 | | bool maximize 307 | * | ) internal view returns (MarketPoolValueInfo.Props memory) { 308 | * | MarketPoolValueInfo.Props memory result; 309 | | 310 | * | result.longTokenAmount = getPoolAmount( 311 | * | dataStore, 312 | * | market, 313 | * | market.longToken 314 | | ); 315 | * | result.shortTokenAmount = getPoolAmount( 316 | * | dataStore, 317 | * | market, 318 | * | market.shortToken 319 | | ); 320 | | 321 | * | result.longTokenUsd = 322 | * | result.longTokenAmount * 323 | * | longTokenPrice.pickPrice(maximize); 324 | * | result.shortTokenUsd = 325 | * | result.shortTokenAmount * 326 | * | shortTokenPrice.pickPrice(maximize); 327 | | 328 | * | result.poolValue = (result.longTokenUsd + result.shortTokenUsd) 329 | | .toInt256(); 330 | | 331 | * | MarketPrices memory prices = MarketPrices( 332 | * | indexTokenPrice, 333 | * | longTokenPrice, 334 | * | shortTokenPrice 335 | | ); 336 | | 337 | * | result.totalBorrowingFees = getTotalPendingBorrowingFees( 338 | * | dataStore, 339 | * | market, 340 | * | prices, 341 | * | true 342 | | ); 343 | | 344 | * | result.totalBorrowingFees += getTotalPendingBorrowingFees( 345 | * | dataStore, 346 | * | market, 347 | * | prices, 348 | * | false 349 | | ); 350 | | 351 | * | result.borrowingFeePoolFactor = 352 | * | Precision.FLOAT_PRECISION - 353 | * | dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR); 354 | * | result.poolValue += Precision 355 | | .applyFactor( 356 | * | result.totalBorrowingFees, 357 | * | result.borrowingFeePoolFactor 358 | | ) 359 | | .toInt256(); 360 | | 361 | | // !maximize should be used for net pnl as a larger pnl leads to a smaller pool value 362 | | // and a smaller pnl leads to a larger pool value 363 | | // 364 | | // while positions will always be closed at the less favourable price 365 | | // using the inverse of maximize for the getPnl calls would help prevent 366 | | // gaming of market token values by increasing the spread 367 | | // 368 | | // liquidations could be triggerred by manipulating a large spread but 369 | | // that should be more difficult to execute 370 | | 371 | * | result.longPnl = getPnl( 372 | * | dataStore, 373 | * | market, 374 | * | indexTokenPrice, 375 | * | true, // isLong 376 | * | !maximize // maximize 377 | | ); 378 | | 379 | * | result.longPnl = getCappedPnl( 380 | * | dataStore, 381 | * | market.marketToken, 382 | * | true, 383 | * | result.longPnl, 384 | * | result.longTokenUsd, 385 | * | pnlFactorType 386 | | ); 387 | | 388 | * | result.shortPnl = getPnl( 389 | * | dataStore, 390 | * | market, 391 | * | indexTokenPrice, 392 | * | false, // isLong 393 | * | !maximize // maximize 394 | | ); 395 | | 396 | * | result.shortPnl = getCappedPnl( 397 | * | dataStore, 398 | * | market.marketToken, 399 | * | false, 400 | * | result.shortPnl, 401 | * | result.shortTokenUsd, 402 | * | pnlFactorType 403 | | ); 404 | | 405 | * | result.netPnl = result.longPnl + result.shortPnl; 406 | * | result.poolValue = result.poolValue - result.netPnl; 407 | | 408 | * | result.impactPoolAmount = getNextPositionImpactPoolAmount( 409 | * | dataStore, 410 | * | market.marketToken 411 | | ); 412 | | // use !maximize for pickPrice since the impactPoolUsd is deducted from the poolValue 413 | * | uint256 impactPoolUsd = result.impactPoolAmount * 414 | * | indexTokenPrice.pickPrice(!maximize); 415 | | 416 | * | result.poolValue -= impactPoolUsd.toInt256(); 417 | | 418 | * | return result; 419 | | } 420 | | 421 | | // @dev get the net pending pnl for a market 422 | | // @param dataStore DataStore 423 | | // @param market the market to check 424 | | // @param longToken the long token of the market 425 | | // @param shortToken the short token of the market 426 | | // @param indexTokenPrice the price of the index token 427 | | // @param maximize whether to maximize or minimize the net pnl 428 | | // @return the net pending pnl for a market 429 | | function getNetPnl( 430 | | DataStore dataStore, 431 | | Market.Props memory market, 432 | | Price.Props memory indexTokenPrice, 433 | | bool maximize 434 | | ) internal view returns (int256) { 435 | | int256 longPnl = getPnl( 436 | | dataStore, 437 | | market, 438 | | indexTokenPrice, 439 | | true, 440 | | maximize 441 | | ); 442 | | int256 shortPnl = getPnl( 443 | | dataStore, 444 | | market, 445 | | indexTokenPrice, 446 | | false, 447 | | maximize 448 | | ); 449 | | 450 | | return longPnl + shortPnl; 451 | | } 452 | | 453 | | // @dev get the capped pending pnl for a market 454 | | // @param dataStore DataStore 455 | | // @param market the market to check 456 | | // @param isLong whether to check for the long or short side 457 | | // @param pnl the uncapped pnl of the market 458 | | // @param poolUsd the USD value of the pool 459 | | // @param pnlFactorType the pnl factor type to use 460 | * | function getCappedPnl( 461 | | DataStore dataStore, 462 | | address market, 463 | | bool isLong, 464 | | int256 pnl, 465 | | uint256 poolUsd, 466 | | bytes32 pnlFactorType 467 | * | ) internal view returns (int256) { 468 | * | if (pnl < 0) { 469 | * | return pnl; 470 | | } 471 | | 472 | * | uint256 maxPnlFactor = getMaxPnlFactor( 473 | * | dataStore, 474 | * | pnlFactorType, 475 | * | market, 476 | * | isLong 477 | | ); 478 | * | int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256(); 479 | | 480 | * | return pnl > maxPnl ? maxPnl : pnl; 481 | | } 482 | | 483 | | // @dev get the pending pnl for a market 484 | | // @param dataStore DataStore 485 | | // @param market the market to check 486 | | // @param longToken the long token of the market 487 | | // @param shortToken the short token of the market 488 | | // @param indexTokenPrice the price of the index token 489 | | // @param isLong whether to check for the long or short side 490 | | // @param maximize whether to maximize or minimize the pnl 491 | | function getPnl( 492 | | DataStore dataStore, 493 | | Market.Props memory market, 494 | | uint256 indexTokenPrice, 495 | | bool isLong, 496 | | bool maximize 497 | | ) internal view returns (int256) { 498 | | Price.Props memory _indexTokenPrice = Price.Props( 499 | | indexTokenPrice, 500 | | indexTokenPrice 501 | | ); 502 | | 503 | | return getPnl(dataStore, market, _indexTokenPrice, isLong, maximize); 504 | | } 505 | | 506 | | // @dev get the pending pnl for a market for either longs or shorts 507 | | // @param dataStore DataStore 508 | | // @param market the market to check 509 | | // @param longToken the long token of the market 510 | | // @param shortToken the short token of the market 511 | | // @param indexTokenPrice the price of the index token 512 | | // @param isLong whether to get the pnl for longs or shorts 513 | | // @param maximize whether to maximize or minimize the net pnl 514 | | // @return the pending pnl for a market for either longs or shorts 515 | * | function getPnl( 516 | | DataStore dataStore, 517 | | Market.Props memory market, 518 | | Price.Props memory indexTokenPrice, 519 | | bool isLong, 520 | | bool maximize 521 | * | ) internal view returns (int256) { 522 | * | int256 openInterest = getOpenInterest(dataStore, market, isLong) 523 | | .toInt256(); 524 | * | uint256 openInterestInTokens = getOpenInterestInTokens( 525 | * | dataStore, 526 | * | market, 527 | * | isLong 528 | | ); 529 | * | if (openInterest == 0 || openInterestInTokens == 0) { 530 | * | return 0; 531 | | } 532 | | 533 | * | uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize); 534 | | 535 | | // openInterest is the cost of all positions, openInterestValue is the current worth of all positions 536 | * | int256 openInterestValue = (openInterestInTokens * price).toInt256(); 537 | * | int256 pnl = isLong 538 | * | ? openInterestValue - openInterest 539 | * | : openInterest - openInterestValue; 540 | | 541 | * | return pnl; 542 | | } 543 | | 544 | | // @dev get the amount of tokens in the pool 545 | | // @param dataStore DataStore 546 | | // @param market the market to check 547 | | // @param token the token to check 548 | | // @return the amount of tokens in the pool 549 | * | function getPoolAmount( 550 | | DataStore dataStore, 551 | | Market.Props memory market, 552 | | address token 553 | * | ) internal view returns (uint256) { 554 | | /* Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); */ 555 | | // if the longToken and shortToken are the same, return half of the token amount, so that 556 | | // calculations of pool value, etc would be correct 557 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 558 | * | return 559 | * | dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / 560 | * | divisor; 561 | | } 562 | | 563 | | // @dev get the max amount of tokens allowed to be in the pool 564 | | // @param dataStore DataStore 565 | | // @param market the market to check 566 | | // @param token the token to check 567 | | // @return the max amount of tokens that are allowed in the pool 568 | * | function getMaxPoolAmount( 569 | | DataStore dataStore, 570 | | address market, 571 | | address token 572 | * | ) internal view returns (uint256) { 573 | * | return dataStore.getUint(Keys.maxPoolAmountKey(market, token)); 574 | | } 575 | | 576 | * | function getMaxPoolUsdForDeposit( 577 | | DataStore dataStore, 578 | | address market, 579 | | address token 580 | * | ) internal view returns (uint256) { 581 | * | return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token)); 582 | | } 583 | | 584 | | function getUsageFactor( 585 | | DataStore dataStore, 586 | | Market.Props memory market, 587 | | bool isLong, 588 | | uint256 reservedUsd, 589 | | uint256 poolUsd 590 | | ) internal view returns (uint256) { 591 | | uint256 reserveFactor = getOpenInterestReserveFactor( 592 | | dataStore, 593 | | market.marketToken, 594 | | isLong 595 | | ); 596 | | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor); 597 | | uint256 reserveUsageFactor = Precision.toFactor( 598 | | reservedUsd, 599 | | maxReservedUsd 600 | | ); 601 | | 602 | | uint256 maxOpenInterest = getMaxOpenInterest( 603 | | dataStore, 604 | | market.marketToken, 605 | | isLong 606 | | ); 607 | | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 608 | | uint256 openInterestUsageFactor = Precision.toFactor( 609 | | openInterest, 610 | | maxOpenInterest 611 | | ); 612 | | 613 | | return 614 | | reserveUsageFactor > openInterestUsageFactor 615 | | ? reserveUsageFactor 616 | | : openInterestUsageFactor; 617 | | } 618 | | 619 | | // @dev get the max open interest allowed for the market 620 | | // @param dataStore DataStore 621 | | // @param market the market to check 622 | | // @param isLong whether this is for the long or short side 623 | | // @return the max open interest allowed for the market 624 | * | function getMaxOpenInterest( 625 | | DataStore dataStore, 626 | | address market, 627 | | bool isLong 628 | * | ) internal view returns (uint256) { 629 | * | return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong)); 630 | | } 631 | | 632 | | // @dev increment the claimable collateral amount 633 | | // @param dataStore DataStore 634 | | // @param eventEmitter EventEmitter 635 | | // @param market the market to increment the claimable collateral for 636 | | // @param token the claimable token 637 | | // @param account the account to increment the claimable collateral for 638 | | // @param delta the amount to increment 639 | | function incrementClaimableCollateralAmount( 640 | | DataStore dataStore, 641 | | EventEmitter eventEmitter, 642 | | address market, 643 | | address token, 644 | | address account, 645 | | uint256 delta 646 | | ) internal { 647 | | uint256 divisor = dataStore.getUint( 648 | | Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR 649 | | ); 650 | | uint256 timeKey = Chain.currentTimestamp() / divisor; 651 | | 652 | | uint256 nextValue = dataStore.incrementUint( 653 | | Keys.claimableCollateralAmountKey(market, token, timeKey, account), 654 | | delta 655 | | ); 656 | | 657 | | uint256 nextPoolValue = dataStore.incrementUint( 658 | | Keys.claimableCollateralAmountKey(market, token), 659 | | delta 660 | | ); 661 | | 662 | | MarketEventUtils.emitClaimableCollateralUpdated( 663 | | eventEmitter, 664 | | market, 665 | | token, 666 | | timeKey, 667 | | account, 668 | | delta, 669 | | nextValue, 670 | | nextPoolValue 671 | | ); 672 | | } 673 | | 674 | | // @dev increment the claimable funding amount 675 | | // @param dataStore DataStore 676 | | // @param eventEmitter EventEmitter 677 | | // @param market the trading market 678 | | // @param token the claimable token 679 | | // @param account the account to increment for 680 | | // @param delta the amount to increment 681 | * | function incrementClaimableFundingAmount( 682 | | DataStore dataStore, 683 | | EventEmitter eventEmitter, 684 | | address market, 685 | | address token, 686 | | address account, 687 | | uint256 delta 688 | * | ) internal { 689 | * | uint256 nextValue = dataStore.incrementUint( 690 | * | Keys.claimableFundingAmountKey(market, token, account), 691 | * | delta 692 | | ); 693 | | 694 | * | uint256 nextPoolValue = dataStore.incrementUint( 695 | * | Keys.claimableFundingAmountKey(market, token), 696 | * | delta 697 | | ); 698 | | 699 | * | MarketEventUtils.emitClaimableFundingUpdated( 700 | * | eventEmitter, 701 | * | market, 702 | * | token, 703 | * | account, 704 | * | delta, 705 | * | nextValue, 706 | * | nextPoolValue 707 | | ); 708 | | } 709 | | 710 | | // @dev claim funding fees 711 | | // @param dataStore DataStore 712 | | // @param eventEmitter EventEmitter 713 | | // @param market the market to claim for 714 | | // @param token the token to claim 715 | | // @param account the account to claim for 716 | | // @param receiver the receiver to send the amount to 717 | * | function claimFundingFees( 718 | | DataStore dataStore, 719 | | EventEmitter eventEmitter, 720 | | address market, 721 | | address token, 722 | | address account, 723 | | address receiver 724 | * | ) internal returns (uint256) { 725 | * | bytes32 key = Keys.claimableFundingAmountKey(market, token, account); 726 | | 727 | * | uint256 claimableAmount = dataStore.getUint(key); 728 | * | dataStore.setUint(key, 0); 729 | | 730 | * | uint256 nextPoolValue = dataStore.decrementUint( 731 | * | Keys.claimableFundingAmountKey(market, token), 732 | * | claimableAmount 733 | | ); 734 | | 735 | * | MarketToken(payable(market)).transferOut( 736 | * | token, 737 | * | receiver, 738 | * | claimableAmount 739 | | ); 740 | | 741 | * | validateMarketTokenBalance(dataStore, market); 742 | | 743 | * | MarketEventUtils.emitFundingFeesClaimed( 744 | * | eventEmitter, 745 | * | market, 746 | * | token, 747 | * | account, 748 | * | receiver, 749 | * | claimableAmount, 750 | * | nextPoolValue 751 | | ); 752 | | 753 | * | return claimableAmount; 754 | | } 755 | | 756 | | // @dev claim collateral 757 | | // @param dataStore DataStore 758 | | // @param eventEmitter EventEmitter 759 | | // @param market the market to claim for 760 | | // @param token the token to claim 761 | | // @param timeKey the time key 762 | | // @param account the account to claim for 763 | | // @param receiver the receiver to send the amount to 764 | | function claimCollateral( 765 | | DataStore dataStore, 766 | | EventEmitter eventEmitter, 767 | | address market, 768 | | address token, 769 | | uint256 timeKey, 770 | | address account, 771 | | address receiver 772 | | ) internal returns (uint256) { 773 | | uint256 claimableAmount = dataStore.getUint( 774 | | Keys.claimableCollateralAmountKey(market, token, timeKey, account) 775 | | ); 776 | | 777 | | uint256 claimableFactor; 778 | | 779 | | { 780 | | uint256 claimableFactorForTime = dataStore.getUint( 781 | | Keys.claimableCollateralFactorKey(market, token, timeKey) 782 | | ); 783 | | uint256 claimableFactorForAccount = dataStore.getUint( 784 | | Keys.claimableCollateralFactorKey( 785 | | market, 786 | | token, 787 | | timeKey, 788 | | account 789 | | ) 790 | | ); 791 | | claimableFactor = claimableFactorForTime > claimableFactorForAccount 792 | | ? claimableFactorForTime 793 | | : claimableFactorForAccount; 794 | | } 795 | | 796 | | if (claimableFactor > Precision.FLOAT_PRECISION) { 797 | | revert Errors.InvalidClaimableFactor(claimableFactor); 798 | | } 799 | | 800 | | uint256 claimedAmount = dataStore.getUint( 801 | | Keys.claimedCollateralAmountKey(market, token, timeKey, account) 802 | | ); 803 | | 804 | | uint256 adjustedClaimableAmount = Precision.applyFactor( 805 | | claimableAmount, 806 | | claimableFactor 807 | | ); 808 | | if (adjustedClaimableAmount <= claimedAmount) { 809 | | revert Errors.CollateralAlreadyClaimed( 810 | | adjustedClaimableAmount, 811 | | claimedAmount 812 | | ); 813 | | } 814 | | 815 | | uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount; 816 | | 817 | | dataStore.setUint( 818 | | Keys.claimedCollateralAmountKey(market, token, timeKey, account), 819 | | adjustedClaimableAmount 820 | | ); 821 | | 822 | | uint256 nextPoolValue = dataStore.decrementUint( 823 | | Keys.claimableCollateralAmountKey(market, token), 824 | | amountToBeClaimed 825 | | ); 826 | | 827 | | MarketToken(payable(market)).transferOut( 828 | | token, 829 | | receiver, 830 | | amountToBeClaimed 831 | | ); 832 | | 833 | | validateMarketTokenBalance(dataStore, market); 834 | | 835 | | MarketEventUtils.emitCollateralClaimed( 836 | | eventEmitter, 837 | | market, 838 | | token, 839 | | timeKey, 840 | | account, 841 | | receiver, 842 | | amountToBeClaimed, 843 | | nextPoolValue 844 | | ); 845 | | 846 | | return amountToBeClaimed; 847 | | } 848 | | 849 | | // @dev apply a delta to the pool amount 850 | | // validatePoolAmount is not called in this function since applyDeltaToPoolAmount 851 | | // is called when receiving fees 852 | | // @param dataStore DataStore 853 | | // @param eventEmitter EventEmitter 854 | | // @param market the market to apply to 855 | | // @param token the token to apply to 856 | | // @param delta the delta amount 857 | * | function applyDeltaToPoolAmount( 858 | | DataStore dataStore, 859 | | EventEmitter eventEmitter, 860 | | Market.Props memory market, 861 | | address token, 862 | | int256 delta 863 | * | ) internal returns (uint256) { 864 | * | uint256 nextValue = dataStore.applyDeltaToUint( 865 | * | Keys.poolAmountKey(market.marketToken, token), 866 | * | delta, 867 | | "Invalid state, negative poolAmount" 868 | | ); 869 | | 870 | * | applyDeltaToVirtualInventoryForSwaps( 871 | * | dataStore, 872 | * | eventEmitter, 873 | * | market, 874 | * | token, 875 | * | delta 876 | | ); 877 | | 878 | * | MarketEventUtils.emitPoolAmountUpdated( 879 | * | eventEmitter, 880 | * | market.marketToken, 881 | * | token, 882 | * | delta, 883 | * | nextValue 884 | | ); 885 | | 886 | * | return nextValue; 887 | | } 888 | | 889 | * | function getAdjustedSwapImpactFactor( 890 | | DataStore dataStore, 891 | | address market, 892 | | bool isPositive 893 | * | ) internal view returns (uint256) { 894 | * | ( 895 | * | uint256 positiveImpactFactor, 896 | * | uint256 negativeImpactFactor 897 | * | ) = getAdjustedSwapImpactFactors(dataStore, market); 898 | | 899 | * | return isPositive ? positiveImpactFactor : negativeImpactFactor; 900 | | } 901 | | 902 | * | function getAdjustedSwapImpactFactors( 903 | | DataStore dataStore, 904 | | address market 905 | * | ) internal view returns (uint256, uint256) { 906 | * | uint256 positiveImpactFactor = dataStore.getUint( 907 | * | Keys.swapImpactFactorKey(market, true) 908 | | ); 909 | * | uint256 negativeImpactFactor = dataStore.getUint( 910 | * | Keys.swapImpactFactorKey(market, false) 911 | | ); 912 | | 913 | | // if the positive impact factor is more than the negative impact factor, positions could be opened 914 | | // and closed immediately for a profit if the difference is sufficient to cover the position fees 915 | * | if (positiveImpactFactor > negativeImpactFactor) { 916 | | positiveImpactFactor = negativeImpactFactor; 917 | | } 918 | | 919 | * | return (positiveImpactFactor, negativeImpactFactor); 920 | | } 921 | | 922 | * | function getAdjustedPositionImpactFactor( 923 | | DataStore dataStore, 924 | | address market, 925 | | bool isPositive 926 | * | ) internal view returns (uint256) { 927 | * | ( 928 | * | uint256 positiveImpactFactor, 929 | * | uint256 negativeImpactFactor 930 | * | ) = getAdjustedPositionImpactFactors(dataStore, market); 931 | | 932 | * | return isPositive ? positiveImpactFactor : negativeImpactFactor; 933 | | } 934 | | 935 | * | function getAdjustedPositionImpactFactors( 936 | | DataStore dataStore, 937 | | address market 938 | * | ) internal view returns (uint256, uint256) { 939 | * | uint256 positiveImpactFactor = dataStore.getUint( 940 | * | Keys.positionImpactFactorKey(market, true) 941 | | ); 942 | * | uint256 negativeImpactFactor = dataStore.getUint( 943 | * | Keys.positionImpactFactorKey(market, false) 944 | | ); 945 | | 946 | | // if the positive impact factor is more than the negative impact factor, positions could be opened 947 | | // and closed immediately for a profit if the difference is sufficient to cover the position fees 948 | * | if (positiveImpactFactor > negativeImpactFactor) { 949 | | positiveImpactFactor = negativeImpactFactor; 950 | | } 951 | | 952 | * | return (positiveImpactFactor, negativeImpactFactor); 953 | | } 954 | | 955 | | // @dev cap the input priceImpactUsd by the available amount in the position 956 | | // impact pool and the max positive position impact factor 957 | | // @param dataStore DataStore 958 | | // @param market the trading market 959 | | // @param tokenPrice the price of the token 960 | | // @param priceImpactUsd the calculated USD price impact 961 | | // @return the capped priceImpactUsd 962 | * | function getCappedPositionImpactUsd( 963 | | DataStore dataStore, 964 | | address market, 965 | | Price.Props memory indexTokenPrice, 966 | | int256 priceImpactUsd, 967 | | uint256 sizeDeltaUsd 968 | * | ) internal view returns (int256) { 969 | * | if (priceImpactUsd < 0) { 970 | * | return priceImpactUsd; 971 | | } 972 | | 973 | * | uint256 impactPoolAmount = getPositionImpactPoolAmount( 974 | * | dataStore, 975 | * | market 976 | | ); 977 | * | int256 maxPriceImpactUsdBasedOnImpactPool = (impactPoolAmount * 978 | * | indexTokenPrice.min).toInt256(); 979 | | 980 | * | if (priceImpactUsd > maxPriceImpactUsdBasedOnImpactPool) { 981 | * | priceImpactUsd = maxPriceImpactUsdBasedOnImpactPool; 982 | | } 983 | | 984 | * | uint256 maxPriceImpactFactor = getMaxPositionImpactFactor( 985 | * | dataStore, 986 | * | market, 987 | * | true 988 | | ); 989 | * | int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision 990 | * | .applyFactor(sizeDeltaUsd, maxPriceImpactFactor) 991 | | .toInt256(); 992 | | 993 | * | if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) { 994 | * | priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor; 995 | | } 996 | | 997 | * | return priceImpactUsd; 998 | | } 999 | | 1000 | | // @dev get the position impact pool amount 1001 | | // @param dataStore DataStore 1002 | | // @param market the market to check 1003 | | // @return the position impact pool amount 1004 | * | function getPositionImpactPoolAmount( 1005 | | DataStore dataStore, 1006 | | address market 1007 | * | ) internal view returns (uint256) { 1008 | * | return dataStore.getUint(Keys.positionImpactPoolAmountKey(market)); 1009 | | } 1010 | | 1011 | | // @dev get the swap impact pool amount 1012 | | // @param dataStore DataStore 1013 | | // @param market the market to check 1014 | | // @param token the token to check 1015 | | // @return the swap impact pool amount 1016 | * | function getSwapImpactPoolAmount( 1017 | | DataStore dataStore, 1018 | | address market, 1019 | | address token 1020 | * | ) internal view returns (uint256) { 1021 | * | return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token)); 1022 | | } 1023 | | 1024 | | // @dev apply a delta to the swap impact pool 1025 | | // @param dataStore DataStore 1026 | | // @param eventEmitter EventEmitter 1027 | | // @param market the market to apply to 1028 | | // @param token the token to apply to 1029 | | // @param delta the delta amount 1030 | * | function applyDeltaToSwapImpactPool( 1031 | | DataStore dataStore, 1032 | | EventEmitter eventEmitter, 1033 | | address market, 1034 | | address token, 1035 | | int256 delta 1036 | * | ) internal returns (uint256) { 1037 | * | uint256 nextValue = dataStore.applyBoundedDeltaToUint( 1038 | * | Keys.swapImpactPoolAmountKey(market, token), 1039 | * | delta 1040 | | ); 1041 | | 1042 | * | MarketEventUtils.emitSwapImpactPoolAmountUpdated( 1043 | * | eventEmitter, 1044 | * | market, 1045 | * | token, 1046 | * | delta, 1047 | * | nextValue 1048 | | ); 1049 | | 1050 | * | return nextValue; 1051 | | } 1052 | | 1053 | | // @dev apply a delta to the position impact pool 1054 | | // @param dataStore DataStore 1055 | | // @param eventEmitter EventEmitter 1056 | | // @param market the market to apply to 1057 | | // @param delta the delta amount 1058 | * | function applyDeltaToPositionImpactPool( 1059 | | DataStore dataStore, 1060 | | EventEmitter eventEmitter, 1061 | | address market, 1062 | | int256 delta 1063 | * | ) internal returns (uint256) { 1064 | * | uint256 nextValue = dataStore.applyBoundedDeltaToUint( 1065 | * | Keys.positionImpactPoolAmountKey(market), 1066 | * | delta 1067 | | ); 1068 | | 1069 | * | MarketEventUtils.emitPositionImpactPoolAmountUpdated( 1070 | * | eventEmitter, 1071 | * | market, 1072 | * | delta, 1073 | * | nextValue 1074 | | ); 1075 | | 1076 | * | return nextValue; 1077 | | } 1078 | | 1079 | | // @dev apply a delta to the open interest 1080 | | // @param dataStore DataStore 1081 | | // @param eventEmitter EventEmitter 1082 | | // @param market the market to apply to 1083 | | // @param collateralToken the collateralToken to apply to 1084 | | // @param isLong whether to apply to the long or short side 1085 | | // @param delta the delta amount 1086 | * | function applyDeltaToOpenInterest( 1087 | | DataStore dataStore, 1088 | | EventEmitter eventEmitter, 1089 | | Market.Props memory market, 1090 | | address collateralToken, 1091 | | bool isLong, 1092 | | int256 delta 1093 | * | ) internal returns (uint256) { 1094 | * | if (market.indexToken == address(0)) { 1095 | | revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket( 1096 | | market.marketToken 1097 | | ); 1098 | | } 1099 | | 1100 | * | uint256 nextValue = dataStore.applyDeltaToUint( 1101 | * | Keys.openInterestKey(market.marketToken, collateralToken, isLong), 1102 | * | delta, 1103 | | "Invalid state: negative open interest" 1104 | | ); 1105 | | 1106 | | // if the open interest for longs is increased then tokens were virtually bought from the pool 1107 | | // so the virtual inventory should be decreased 1108 | | // if the open interest for longs is decreased then tokens were virtually sold to the pool 1109 | | // so the virtual inventory should be increased 1110 | | // if the open interest for shorts is increased then tokens were virtually sold to the pool 1111 | | // so the virtual inventory should be increased 1112 | | // if the open interest for shorts is decreased then tokens were virtually bought from the pool 1113 | | // so the virtual inventory should be decreased 1114 | * | applyDeltaToVirtualInventoryForPositions( 1115 | * | dataStore, 1116 | * | eventEmitter, 1117 | * | market.indexToken, 1118 | * | isLong ? -delta : delta 1119 | | ); 1120 | | 1121 | * | if (delta > 0) { 1122 | * | validateOpenInterest(dataStore, market, isLong); 1123 | | } 1124 | | 1125 | * | MarketEventUtils.emitOpenInterestUpdated( 1126 | * | eventEmitter, 1127 | * | market.marketToken, 1128 | * | collateralToken, 1129 | * | isLong, 1130 | * | delta, 1131 | * | nextValue 1132 | | ); 1133 | | 1134 | * | return nextValue; 1135 | | } 1136 | | 1137 | | // @dev apply a delta to the open interest in tokens 1138 | | // @param dataStore DataStore 1139 | | // @param eventEmitter EventEmitter 1140 | | // @param market the market to apply to 1141 | | // @param collateralToken the collateralToken to apply to 1142 | | // @param isLong whether to apply to the long or short side 1143 | | // @param delta the delta amount 1144 | * | function applyDeltaToOpenInterestInTokens( 1145 | | DataStore dataStore, 1146 | | EventEmitter eventEmitter, 1147 | | address market, 1148 | | address collateralToken, 1149 | | bool isLong, 1150 | | int256 delta 1151 | * | ) internal returns (uint256) { 1152 | * | uint256 nextValue = dataStore.applyDeltaToUint( 1153 | * | Keys.openInterestInTokensKey(market, collateralToken, isLong), 1154 | * | delta, 1155 | | "Invalid state: negative open interest in tokens" 1156 | | ); 1157 | | 1158 | * | MarketEventUtils.emitOpenInterestInTokensUpdated( 1159 | * | eventEmitter, 1160 | * | market, 1161 | * | collateralToken, 1162 | * | isLong, 1163 | * | delta, 1164 | * | nextValue 1165 | | ); 1166 | | 1167 | * | return nextValue; 1168 | | } 1169 | | 1170 | | // @dev apply a delta to the collateral sum 1171 | | // @param dataStore DataStore 1172 | | // @param eventEmitter EventEmitter 1173 | | // @param market the market to apply to 1174 | | // @param collateralToken the collateralToken to apply to 1175 | | // @param isLong whether to apply to the long or short side 1176 | | // @param delta the delta amount 1177 | * | function applyDeltaToCollateralSum( 1178 | | DataStore dataStore, 1179 | | EventEmitter eventEmitter, 1180 | | address market, 1181 | | address collateralToken, 1182 | | bool isLong, 1183 | | int256 delta 1184 | * | ) internal returns (uint256) { 1185 | * | uint256 nextValue = dataStore.applyDeltaToUint( 1186 | * | Keys.collateralSumKey(market, collateralToken, isLong), 1187 | * | delta, 1188 | | "Invalid state: negative collateralSum" 1189 | | ); 1190 | | 1191 | * | MarketEventUtils.emitCollateralSumUpdated( 1192 | * | eventEmitter, 1193 | * | market, 1194 | * | collateralToken, 1195 | * | isLong, 1196 | * | delta, 1197 | * | nextValue 1198 | | ); 1199 | | 1200 | * | return nextValue; 1201 | | } 1202 | | 1203 | | // @dev update the funding state 1204 | | // @param dataStore DataStore 1205 | | // @param market the market to update 1206 | | // @param prices the prices of the market tokens 1207 | * | function updateFundingState( 1208 | | DataStore dataStore, 1209 | | EventEmitter eventEmitter, 1210 | | Market.Props memory market, 1211 | | MarketPrices memory prices 1212 | * | ) internal { 1213 | * | GetNextFundingAmountPerSizeResult 1214 | * | memory result = getNextFundingAmountPerSize( 1215 | * | dataStore, 1216 | * | market, 1217 | * | prices 1218 | | ); 1219 | | 1220 | * | applyDeltaToFundingFeeAmountPerSize( 1221 | * | dataStore, 1222 | * | eventEmitter, 1223 | * | market.marketToken, 1224 | * | market.longToken, 1225 | * | true, 1226 | * | result.fundingFeeAmountPerSizeDelta.long.longToken 1227 | | ); 1228 | | 1229 | * | applyDeltaToFundingFeeAmountPerSize( 1230 | * | dataStore, 1231 | * | eventEmitter, 1232 | * | market.marketToken, 1233 | * | market.longToken, 1234 | * | false, 1235 | * | result.fundingFeeAmountPerSizeDelta.short.longToken 1236 | | ); 1237 | | 1238 | * | applyDeltaToFundingFeeAmountPerSize( 1239 | * | dataStore, 1240 | * | eventEmitter, 1241 | * | market.marketToken, 1242 | * | market.shortToken, 1243 | * | true, 1244 | * | result.fundingFeeAmountPerSizeDelta.long.shortToken 1245 | | ); 1246 | | 1247 | * | applyDeltaToFundingFeeAmountPerSize( 1248 | * | dataStore, 1249 | * | eventEmitter, 1250 | * | market.marketToken, 1251 | * | market.shortToken, 1252 | * | false, 1253 | * | result.fundingFeeAmountPerSizeDelta.short.shortToken 1254 | | ); 1255 | | 1256 | * | applyDeltaToClaimableFundingAmountPerSize( 1257 | * | dataStore, 1258 | * | eventEmitter, 1259 | * | market.marketToken, 1260 | * | market.longToken, 1261 | * | true, 1262 | * | result.claimableFundingAmountPerSizeDelta.long.longToken 1263 | | ); 1264 | | 1265 | * | applyDeltaToClaimableFundingAmountPerSize( 1266 | * | dataStore, 1267 | * | eventEmitter, 1268 | * | market.marketToken, 1269 | * | market.longToken, 1270 | * | false, 1271 | * | result.claimableFundingAmountPerSizeDelta.short.longToken 1272 | | ); 1273 | | 1274 | * | applyDeltaToClaimableFundingAmountPerSize( 1275 | * | dataStore, 1276 | * | eventEmitter, 1277 | * | market.marketToken, 1278 | * | market.shortToken, 1279 | * | true, 1280 | * | result.claimableFundingAmountPerSizeDelta.long.shortToken 1281 | | ); 1282 | | 1283 | * | applyDeltaToClaimableFundingAmountPerSize( 1284 | * | dataStore, 1285 | * | eventEmitter, 1286 | * | market.marketToken, 1287 | * | market.shortToken, 1288 | * | false, 1289 | * | result.claimableFundingAmountPerSizeDelta.short.shortToken 1290 | | ); 1291 | | 1292 | * | setSavedFundingFactorPerSecond( 1293 | * | dataStore, 1294 | * | market.marketToken, 1295 | * | result.nextSavedFundingFactorPerSecond 1296 | | ); 1297 | | 1298 | * | dataStore.setUint( 1299 | * | Keys.fundingUpdatedAtKey(market.marketToken), 1300 | * | Chain.currentTimestamp() 1301 | | ); 1302 | | } 1303 | | 1304 | | // @dev get the next funding amount per size values 1305 | | // @param dataStore DataStore 1306 | | // @param prices the prices of the market tokens 1307 | | // @param market the market to update 1308 | | // @param longToken the market's long token 1309 | | // @param shortToken the market's short token 1310 | * | function getNextFundingAmountPerSize( 1311 | | DataStore dataStore, 1312 | | Market.Props memory market, 1313 | | MarketPrices memory prices 1314 | * | ) internal view returns (GetNextFundingAmountPerSizeResult memory) { 1315 | * | GetNextFundingAmountPerSizeResult memory result; 1316 | * | GetNextFundingAmountPerSizeCache memory cache; 1317 | | 1318 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 1319 | | 1320 | | // get the open interest values by long / short and by collateral used 1321 | * | cache.openInterest.long.longToken = getOpenInterest( 1322 | * | dataStore, 1323 | * | market.marketToken, 1324 | * | market.longToken, 1325 | * | true, 1326 | * | divisor 1327 | | ); 1328 | * | cache.openInterest.long.shortToken = getOpenInterest( 1329 | * | dataStore, 1330 | * | market.marketToken, 1331 | * | market.shortToken, 1332 | * | true, 1333 | * | divisor 1334 | | ); 1335 | * | cache.openInterest.short.longToken = getOpenInterest( 1336 | * | dataStore, 1337 | * | market.marketToken, 1338 | * | market.longToken, 1339 | * | false, 1340 | * | divisor 1341 | | ); 1342 | * | cache.openInterest.short.shortToken = getOpenInterest( 1343 | * | dataStore, 1344 | * | market.marketToken, 1345 | * | market.shortToken, 1346 | * | false, 1347 | * | divisor 1348 | | ); 1349 | | 1350 | | // sum the open interest values to get the total long and short open interest values 1351 | * | cache.longOpenInterest = 1352 | * | cache.openInterest.long.longToken + 1353 | * | cache.openInterest.long.shortToken; 1354 | * | cache.shortOpenInterest = 1355 | * | cache.openInterest.short.longToken + 1356 | * | cache.openInterest.short.shortToken; 1357 | | 1358 | | // if either long or short open interest is zero, then funding should not be updated 1359 | | // as there would not be any user to pay the funding to 1360 | * | if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) { 1361 | * | return result; 1362 | | } 1363 | | 1364 | | // if the blockchain is not progressing / a market is disabled, funding fees 1365 | | // will continue to accumulate 1366 | | // this should be a rare occurrence so funding fees are not adjusted for this case 1367 | * | cache.durationInSeconds = getSecondsSinceFundingUpdated( 1368 | * | dataStore, 1369 | * | market.marketToken 1370 | | ); 1371 | | 1372 | * | cache.sizeOfLargerSide = cache.longOpenInterest > 1373 | * | cache.shortOpenInterest 1374 | * | ? cache.longOpenInterest 1375 | * | : cache.shortOpenInterest; 1376 | | 1377 | * | ( 1378 | * | result.fundingFactorPerSecond, 1379 | * | result.longsPayShorts, 1380 | * | result.nextSavedFundingFactorPerSecond 1381 | * | ) = getNextFundingFactorPerSecond( 1382 | * | dataStore, 1383 | * | market.marketToken, 1384 | * | cache.longOpenInterest, 1385 | * | cache.shortOpenInterest, 1386 | * | cache.durationInSeconds 1387 | | ); 1388 | | 1389 | | // for single token markets, if there is $200,000 long open interest 1390 | | // and $100,000 short open interest and if the fundingUsd is $8: 1391 | | // fundingUsdForLongCollateral: $4 1392 | | // fundingUsdForShortCollateral: $4 1393 | | // fundingFeeAmountPerSizeDelta.long.longToken: 4 / 100,000 1394 | | // fundingFeeAmountPerSizeDelta.long.shortToken: 4 / 100,000 1395 | | // claimableFundingAmountPerSizeDelta.short.longToken: 4 / 100,000 1396 | | // claimableFundingAmountPerSizeDelta.short.shortToken: 4 / 100,000 1397 | | // 1398 | | // the divisor for fundingFeeAmountPerSizeDelta is 100,000 because the 1399 | | // cache.openInterest.long.longOpenInterest and cache.openInterest.long.shortOpenInterest is divided by 2 1400 | | // 1401 | | // when the fundingFeeAmountPerSize value is incremented, it would be incremented twice: 1402 | | // 4 / 100,000 + 4 / 100,000 = 8 / 100,000 1403 | | // 1404 | | // since the actual long open interest is $200,000, this would result in a total of 8 / 100,000 * 200,000 = $16 being charged 1405 | | // 1406 | | // when the claimableFundingAmountPerSize value is incremented, it would similarly be incremented twice: 1407 | | // 4 / 100,000 + 4 / 100,000 = 8 / 100,000 1408 | | // 1409 | | // when calculating the amount to be claimed, the longTokenClaimableFundingAmountPerSize and shortTokenClaimableFundingAmountPerSize 1410 | | // are compared against the market's claimableFundingAmountPerSize for the longToken and claimableFundingAmountPerSize for the shortToken 1411 | | // 1412 | | // since both these values will be duplicated, the amount claimable would be: 1413 | | // (8 / 100,000 + 8 / 100,000) * 100,000 = $16 1414 | | // 1415 | | // due to these, the fundingUsd should be divided by the divisor 1416 | | 1417 | * | cache.fundingUsd = Precision.applyFactor( 1418 | * | cache.sizeOfLargerSide, 1419 | * | cache.durationInSeconds * result.fundingFactorPerSecond 1420 | | ); 1421 | * | cache.fundingUsd = cache.fundingUsd / divisor; 1422 | | 1423 | | // split the fundingUsd value by long and short collateral 1424 | | // e.g. if the fundingUsd value is $500, and there is $1000 of long open interest using long collateral and $4000 of long open interest 1425 | | // with short collateral, then $100 of funding fees should be paid from long positions using long collateral, $400 of funding fees 1426 | | // should be paid from long positions using short collateral 1427 | | // short positions should receive $100 of funding fees in long collateral and $400 of funding fees in short collateral 1428 | * | if (result.longsPayShorts) { 1429 | * | cache.fundingUsdForLongCollateral = Precision.mulDiv( 1430 | * | cache.fundingUsd, 1431 | * | cache.openInterest.long.longToken, 1432 | * | cache.longOpenInterest 1433 | | ); 1434 | * | cache.fundingUsdForShortCollateral = Precision.mulDiv( 1435 | * | cache.fundingUsd, 1436 | * | cache.openInterest.long.shortToken, 1437 | * | cache.longOpenInterest 1438 | | ); 1439 | | } else { 1440 | * | cache.fundingUsdForLongCollateral = Precision.mulDiv( 1441 | * | cache.fundingUsd, 1442 | * | cache.openInterest.short.longToken, 1443 | * | cache.shortOpenInterest 1444 | | ); 1445 | * | cache.fundingUsdForShortCollateral = Precision.mulDiv( 1446 | * | cache.fundingUsd, 1447 | * | cache.openInterest.short.shortToken, 1448 | * | cache.shortOpenInterest 1449 | | ); 1450 | | } 1451 | | 1452 | | // calculate the change in funding amount per size values 1453 | | // for example, if the fundingUsdForLongCollateral is $100, the longToken price is $2000, the longOpenInterest is $10,000, shortOpenInterest is $5000 1454 | | // if longs pay shorts then the fundingFeeAmountPerSize.long.longToken should be increased by 0.05 tokens per $10,000 or 0.000005 tokens per $1 1455 | | // the claimableFundingAmountPerSize.short.longToken should be increased by 0.05 tokens per $5000 or 0.00001 tokens per $1 1456 | * | if (result.longsPayShorts) { 1457 | | // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received 1458 | | // positions only pay funding in the position's collateral token 1459 | | // so the fundingUsdForLongCollateral is divided by the total long open interest for long positions using the longToken as collateral 1460 | | // and the fundingUsdForShortCollateral is divided by the total long open interest for long positions using the shortToken as collateral 1461 | * | result 1462 | | .fundingFeeAmountPerSizeDelta 1463 | | .long 1464 | * | .longToken = getFundingAmountPerSizeDelta( 1465 | * | cache.fundingUsdForLongCollateral, 1466 | * | cache.openInterest.long.longToken, 1467 | * | prices.longTokenPrice.max, 1468 | * | true // roundUpMagnitude 1469 | | ); 1470 | | 1471 | * | result 1472 | | .fundingFeeAmountPerSizeDelta 1473 | | .long 1474 | * | .shortToken = getFundingAmountPerSizeDelta( 1475 | * | cache.fundingUsdForShortCollateral, 1476 | * | cache.openInterest.long.shortToken, 1477 | * | prices.shortTokenPrice.max, 1478 | * | true // roundUpMagnitude 1479 | | ); 1480 | | 1481 | | // positions receive funding in both the longToken and shortToken 1482 | | // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total short open interest 1483 | * | result 1484 | | .claimableFundingAmountPerSizeDelta 1485 | | .short 1486 | * | .longToken = getFundingAmountPerSizeDelta( 1487 | * | cache.fundingUsdForLongCollateral, 1488 | * | cache.shortOpenInterest, 1489 | * | prices.longTokenPrice.max, 1490 | * | false // roundUpMagnitude 1491 | | ); 1492 | | 1493 | * | result 1494 | | .claimableFundingAmountPerSizeDelta 1495 | | .short 1496 | * | .shortToken = getFundingAmountPerSizeDelta( 1497 | * | cache.fundingUsdForShortCollateral, 1498 | * | cache.shortOpenInterest, 1499 | * | prices.shortTokenPrice.max, 1500 | * | false // roundUpMagnitude 1501 | | ); 1502 | | } else { 1503 | | // use the same longTokenPrice.max and shortTokenPrice.max to calculate the amount to be paid and received 1504 | | // positions only pay funding in the position's collateral token 1505 | | // so the fundingUsdForLongCollateral is divided by the total short open interest for short positions using the longToken as collateral 1506 | | // and the fundingUsdForShortCollateral is divided by the total short open interest for short positions using the shortToken as collateral 1507 | * | result 1508 | | .fundingFeeAmountPerSizeDelta 1509 | | .short 1510 | * | .longToken = getFundingAmountPerSizeDelta( 1511 | * | cache.fundingUsdForLongCollateral, 1512 | * | cache.openInterest.short.longToken, 1513 | * | prices.longTokenPrice.max, 1514 | * | true // roundUpMagnitude 1515 | | ); 1516 | | 1517 | * | result 1518 | | .fundingFeeAmountPerSizeDelta 1519 | | .short 1520 | * | .shortToken = getFundingAmountPerSizeDelta( 1521 | * | cache.fundingUsdForShortCollateral, 1522 | * | cache.openInterest.short.shortToken, 1523 | * | prices.shortTokenPrice.max, 1524 | * | true // roundUpMagnitude 1525 | | ); 1526 | | 1527 | | // positions receive funding in both the longToken and shortToken 1528 | | // so the fundingUsdForLongCollateral and fundingUsdForShortCollateral is divided by the total long open interest 1529 | * | result 1530 | | .claimableFundingAmountPerSizeDelta 1531 | | .long 1532 | * | .longToken = getFundingAmountPerSizeDelta( 1533 | * | cache.fundingUsdForLongCollateral, 1534 | * | cache.longOpenInterest, 1535 | * | prices.longTokenPrice.max, 1536 | * | false // roundUpMagnitude 1537 | | ); 1538 | | 1539 | * | result 1540 | | .claimableFundingAmountPerSizeDelta 1541 | | .long 1542 | * | .shortToken = getFundingAmountPerSizeDelta( 1543 | * | cache.fundingUsdForShortCollateral, 1544 | * | cache.longOpenInterest, 1545 | * | prices.shortTokenPrice.max, 1546 | * | false // roundUpMagnitude 1547 | | ); 1548 | | } 1549 | | 1550 | * | return result; 1551 | | } 1552 | | 1553 | | // @dev get the next funding factor per second 1554 | | // in case the minFundingFactorPerSecond is not zero, and the long / short skew has flipped 1555 | | // if orders are being created frequently it is possible that the minFundingFactorPerSecond prevents 1556 | | // the nextSavedFundingFactorPerSecond from being decreased fast enough for the sign to eventually flip 1557 | | // if it is bound by minFundingFactorPerSecond 1558 | | // for that reason, only the nextFundingFactorPerSecond is bound by minFundingFactorPerSecond 1559 | | // and the nextSavedFundingFactorPerSecond is not bound by minFundingFactorPerSecond 1560 | | // @return nextFundingFactorPerSecond, longsPayShorts, nextSavedFundingFactorPerSecond 1561 | * | function getNextFundingFactorPerSecond( 1562 | | DataStore dataStore, 1563 | | address market, 1564 | | uint256 longOpenInterest, 1565 | | uint256 shortOpenInterest, 1566 | | uint256 durationInSeconds 1567 | * | ) internal view returns (uint256, bool, int256) { 1568 | * | GetNextFundingFactorPerSecondCache memory cache; 1569 | | 1570 | * | cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest); 1571 | * | cache.totalOpenInterest = longOpenInterest + shortOpenInterest; 1572 | | 1573 | * | if (cache.diffUsd == 0) { 1574 | | return (0, true, 0); 1575 | | } 1576 | | 1577 | * | if (cache.totalOpenInterest == 0) { 1578 | | revert Errors.UnableToGetFundingFactorEmptyOpenInterest(); 1579 | | } 1580 | | 1581 | * | cache.fundingExponentFactor = getFundingExponentFactor( 1582 | * | dataStore, 1583 | * | market 1584 | | ); 1585 | | 1586 | * | cache.diffUsdAfterExponent = Precision.applyExponentFactor( 1587 | * | cache.diffUsd, 1588 | * | cache.fundingExponentFactor 1589 | | ); 1590 | * | cache.diffUsdToOpenInterestFactor = Precision.toFactor( 1591 | * | cache.diffUsdAfterExponent, 1592 | * | cache.totalOpenInterest 1593 | | ); 1594 | | 1595 | * | FundingConfigCache memory configCache; 1596 | * | configCache.fundingIncreaseFactorPerSecond = dataStore.getUint( 1597 | * | Keys.fundingIncreaseFactorPerSecondKey(market) 1598 | | ); 1599 | | 1600 | * | if (configCache.fundingIncreaseFactorPerSecond == 0) { 1601 | * | cache.fundingFactor = getFundingFactor(dataStore, market); 1602 | * | uint256 maxFundingFactorPerSecond = dataStore.getUint( 1603 | * | Keys.maxFundingFactorPerSecondKey(market) 1604 | | ); 1605 | | 1606 | | // if there is no fundingIncreaseFactorPerSecond then return the static fundingFactor based on open interest difference 1607 | * | uint256 fundingFactorPerSecond = Precision.applyFactor( 1608 | * | cache.diffUsdToOpenInterestFactor, 1609 | * | cache.fundingFactor 1610 | | ); 1611 | | 1612 | * | if (fundingFactorPerSecond > maxFundingFactorPerSecond) { 1613 | | fundingFactorPerSecond = maxFundingFactorPerSecond; 1614 | | } 1615 | | 1616 | * | return ( 1617 | * | fundingFactorPerSecond, 1618 | * | longOpenInterest > shortOpenInterest, 1619 | * | 0 1620 | | ); 1621 | | } 1622 | | 1623 | | // if the savedFundingFactorPerSecond is positive then longs pay shorts 1624 | | // if the savedFundingFactorPerSecond is negative then shorts pay longs 1625 | | cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond( 1626 | | dataStore, 1627 | | market 1628 | | ); 1629 | | cache.savedFundingFactorPerSecondMagnitude = cache 1630 | | .savedFundingFactorPerSecond 1631 | | .abs(); 1632 | | 1633 | | configCache.thresholdForStableFunding = dataStore.getUint( 1634 | | Keys.thresholdForStableFundingKey(market) 1635 | | ); 1636 | | configCache.thresholdForDecreaseFunding = dataStore.getUint( 1637 | | Keys.thresholdForDecreaseFundingKey(market) 1638 | | ); 1639 | | 1640 | | // set the default of nextSavedFundingFactorPerSecond as the savedFundingFactorPerSecond 1641 | | cache.nextSavedFundingFactorPerSecond = cache 1642 | | .savedFundingFactorPerSecond; 1643 | | 1644 | | // the default will be NoChange 1645 | | FundingRateChangeType fundingRateChangeType; 1646 | | 1647 | | bool isSkewTheSameDirectionAsFunding = (cache 1648 | | .savedFundingFactorPerSecond > 1649 | | 0 && 1650 | | longOpenInterest > shortOpenInterest) || 1651 | | (cache.savedFundingFactorPerSecond < 0 && 1652 | | shortOpenInterest > longOpenInterest); 1653 | | 1654 | | if (isSkewTheSameDirectionAsFunding) { 1655 | | if ( 1656 | | cache.diffUsdToOpenInterestFactor > 1657 | | configCache.thresholdForStableFunding 1658 | | ) { 1659 | | fundingRateChangeType = FundingRateChangeType.Increase; 1660 | | } else if ( 1661 | | cache.diffUsdToOpenInterestFactor < 1662 | | configCache.thresholdForDecreaseFunding 1663 | | ) { 1664 | | fundingRateChangeType = FundingRateChangeType.Decrease; 1665 | | } 1666 | | } else { 1667 | | // if the skew has changed, then the funding should increase in the opposite direction 1668 | | fundingRateChangeType = FundingRateChangeType.Increase; 1669 | | } 1670 | | 1671 | | if (fundingRateChangeType == FundingRateChangeType.Increase) { 1672 | | // increase funding rate 1673 | | int256 increaseValue = Precision 1674 | | .applyFactor( 1675 | | cache.diffUsdToOpenInterestFactor, 1676 | | configCache.fundingIncreaseFactorPerSecond 1677 | | ) 1678 | | .toInt256() * durationInSeconds.toInt256(); 1679 | | 1680 | | // if there are more longs than shorts, then the savedFundingFactorPerSecond should increase 1681 | | // otherwise the savedFundingFactorPerSecond should increase in the opposite direction / decrease 1682 | | if (longOpenInterest < shortOpenInterest) { 1683 | | increaseValue = -increaseValue; 1684 | | } 1685 | | 1686 | | cache.nextSavedFundingFactorPerSecond = 1687 | | cache.savedFundingFactorPerSecond + 1688 | | increaseValue; 1689 | | } 1690 | | 1691 | | if ( 1692 | | fundingRateChangeType == FundingRateChangeType.Decrease && 1693 | | cache.savedFundingFactorPerSecondMagnitude != 0 1694 | | ) { 1695 | | configCache.fundingDecreaseFactorPerSecond = dataStore.getUint( 1696 | | Keys.fundingDecreaseFactorPerSecondKey(market) 1697 | | ); 1698 | | uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * 1699 | | durationInSeconds; 1700 | | 1701 | | if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) { 1702 | | // set the funding factor to 1 or -1 depending on the original savedFundingFactorPerSecond 1703 | | cache.nextSavedFundingFactorPerSecond = 1704 | | cache.savedFundingFactorPerSecond / 1705 | | cache.savedFundingFactorPerSecondMagnitude.toInt256(); 1706 | | } else { 1707 | | // reduce the original savedFundingFactorPerSecond while keeping the original sign of the savedFundingFactorPerSecond 1708 | | int256 sign = cache.savedFundingFactorPerSecond / 1709 | | cache.savedFundingFactorPerSecondMagnitude.toInt256(); 1710 | | cache.nextSavedFundingFactorPerSecond = 1711 | | (cache.savedFundingFactorPerSecondMagnitude - decreaseValue) 1712 | | .toInt256() * 1713 | | sign; 1714 | | } 1715 | | } 1716 | | 1717 | | configCache.minFundingFactorPerSecond = dataStore.getUint( 1718 | | Keys.minFundingFactorPerSecondKey(market) 1719 | | ); 1720 | | configCache.maxFundingFactorPerSecond = dataStore.getUint( 1721 | | Keys.maxFundingFactorPerSecondKey(market) 1722 | | ); 1723 | | 1724 | | cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude( 1725 | | cache.nextSavedFundingFactorPerSecond, 1726 | | 0, 1727 | | configCache.maxFundingFactorPerSecond 1728 | | ); 1729 | | 1730 | | cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude( 1731 | | cache.nextSavedFundingFactorPerSecond, 1732 | | configCache.minFundingFactorPerSecond, 1733 | | configCache.maxFundingFactorPerSecond 1734 | | ); 1735 | | 1736 | | return ( 1737 | | cache.nextSavedFundingFactorPerSecondWithMinBound.abs(), 1738 | | cache.nextSavedFundingFactorPerSecondWithMinBound > 0, 1739 | | cache.nextSavedFundingFactorPerSecond 1740 | | ); 1741 | | } 1742 | | 1743 | | // store funding values as token amount per (Precision.FLOAT_PRECISION_SQRT / Precision.FLOAT_PRECISION) of USD size 1744 | * | function getFundingAmountPerSizeDelta( 1745 | | uint256 fundingUsd, 1746 | | uint256 openInterest, 1747 | | uint256 tokenPrice, 1748 | | bool roundUpMagnitude 1749 | * | ) internal pure returns (uint256) { 1750 | * | if (fundingUsd == 0 || openInterest == 0) { 1751 | * | return 0; 1752 | | } 1753 | | 1754 | * | uint256 fundingUsdPerSize = Precision.mulDiv( 1755 | * | fundingUsd, 1756 | * | Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT, 1757 | * | openInterest, 1758 | * | roundUpMagnitude 1759 | | ); 1760 | | 1761 | * | if (roundUpMagnitude) { 1762 | * | return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice); 1763 | | } else { 1764 | * | return fundingUsdPerSize / tokenPrice; 1765 | | } 1766 | | } 1767 | | 1768 | | // @dev update the cumulative borrowing factor for a market 1769 | | // @param dataStore DataStore 1770 | | // @param market the market to update 1771 | | // @param longToken the market's long token 1772 | | // @param shortToken the market's short token 1773 | | // @param prices the prices of the market tokens 1774 | | // @param isLong whether to update the long or short side 1775 | * | function updateCumulativeBorrowingFactor( 1776 | | DataStore dataStore, 1777 | | EventEmitter eventEmitter, 1778 | | Market.Props memory market, 1779 | | MarketPrices memory prices, 1780 | | bool isLong 1781 | * | ) internal { 1782 | * | ( 1783 | | , 1784 | * | /* uint256 nextCumulativeBorrowingFactor */ uint256 delta 1785 | * | ) = getNextCumulativeBorrowingFactor(dataStore, market, prices, isLong); 1786 | | 1787 | * | incrementCumulativeBorrowingFactor( 1788 | * | dataStore, 1789 | * | eventEmitter, 1790 | * | market.marketToken, 1791 | * | isLong, 1792 | * | delta 1793 | | ); 1794 | | 1795 | * | dataStore.setUint( 1796 | * | Keys.cumulativeBorrowingFactorUpdatedAtKey( 1797 | * | market.marketToken, 1798 | * | isLong 1799 | | ), 1800 | * | Chain.currentTimestamp() 1801 | | ); 1802 | | } 1803 | | 1804 | | // @dev get the ratio of pnl to pool value 1805 | | // @param dataStore DataStore 1806 | | // @param oracle Oracle 1807 | | // @param market the trading market 1808 | | // @param isLong whether to get the value for the long or short side 1809 | | // @param maximize whether to maximize the factor 1810 | | // @return (pnl of positions) / (long or short pool value) 1811 | * | function getPnlToPoolFactor( 1812 | | DataStore dataStore, 1813 | | Oracle oracle, 1814 | | address market, 1815 | | bool isLong, 1816 | | bool maximize 1817 | * | ) internal view returns (int256) { 1818 | * | Market.Props memory _market = getEnabledMarket(dataStore, market); 1819 | * | MarketPrices memory prices = MarketPrices( 1820 | * | oracle.getPrimaryPrice(_market.indexToken), 1821 | * | oracle.getPrimaryPrice(_market.longToken), 1822 | * | oracle.getPrimaryPrice(_market.shortToken) 1823 | | ); 1824 | | 1825 | * | return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize); 1826 | | } 1827 | | 1828 | | // @dev get the ratio of pnl to pool value 1829 | | // @param dataStore DataStore 1830 | | // @param market the market values 1831 | | // @param prices the prices of the market tokens 1832 | | // @param isLong whether to get the value for the long or short side 1833 | | // @param maximize whether to maximize the factor 1834 | | // @return (pnl of positions) / (long or short pool value) 1835 | * | function getPnlToPoolFactor( 1836 | | DataStore dataStore, 1837 | | Market.Props memory market, 1838 | | MarketPrices memory prices, 1839 | | bool isLong, 1840 | | bool maximize 1841 | * | ) internal view returns (int256) { 1842 | * | uint256 poolUsd = getPoolUsdWithoutPnl( 1843 | * | dataStore, 1844 | * | market, 1845 | * | prices, 1846 | * | isLong, 1847 | * | !maximize 1848 | | ); 1849 | | 1850 | * | if (poolUsd == 0) { 1851 | | return 0; 1852 | | } 1853 | | 1854 | * | int256 pnl = getPnl( 1855 | * | dataStore, 1856 | * | market, 1857 | * | prices.indexTokenPrice, 1858 | * | isLong, 1859 | * | maximize 1860 | | ); 1861 | | 1862 | * | return Precision.toFactor(pnl, poolUsd); 1863 | | } 1864 | | 1865 | * | function validateOpenInterest( 1866 | | DataStore dataStore, 1867 | | Market.Props memory market, 1868 | | bool isLong 1869 | * | ) internal view { 1870 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 1871 | * | uint256 maxOpenInterest = getMaxOpenInterest( 1872 | * | dataStore, 1873 | * | market.marketToken, 1874 | * | isLong 1875 | | ); 1876 | | 1877 | * | if (openInterest > maxOpenInterest) { 1878 | * | revert Errors.MaxOpenInterestExceeded( 1879 | * | openInterest, 1880 | * | maxOpenInterest 1881 | | ); 1882 | | } 1883 | | } 1884 | | 1885 | | // @dev validate that the pool amount is within the max allowed amount 1886 | | // @param dataStore DataStore 1887 | | // @param market the market to check 1888 | | // @param token the token to check 1889 | * | function validatePoolAmount( 1890 | | DataStore dataStore, 1891 | | Market.Props memory market, 1892 | | address token 1893 | * | ) internal view { 1894 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token); 1895 | * | uint256 maxPoolAmount = getMaxPoolAmount( 1896 | * | dataStore, 1897 | * | market.marketToken, 1898 | * | token 1899 | | ); 1900 | | 1901 | * | if (poolAmount > maxPoolAmount) { 1902 | | revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount); 1903 | | } 1904 | | } 1905 | | 1906 | * | function validatePoolUsdForDeposit( 1907 | | DataStore dataStore, 1908 | | Market.Props memory market, 1909 | | address token, 1910 | | uint256 tokenPrice 1911 | * | ) internal view { 1912 | * | uint256 poolAmount = getPoolAmount(dataStore, market, token); 1913 | * | uint256 poolUsd = poolAmount * tokenPrice; 1914 | * | uint256 maxPoolUsd = getMaxPoolUsdForDeposit( 1915 | * | dataStore, 1916 | * | market.marketToken, 1917 | * | token 1918 | | ); 1919 | | 1920 | * | if (poolUsd > maxPoolUsd) { 1921 | * | revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd); 1922 | | } 1923 | | } 1924 | | 1925 | | // @dev validate that the amount of tokens required to be reserved 1926 | | // is below the configured threshold 1927 | | // @param dataStore DataStore 1928 | | // @param market the market values 1929 | | // @param prices the prices of the market tokens 1930 | | // @param isLong whether to check the long or short side 1931 | * | function validateReserve( 1932 | | DataStore dataStore, 1933 | | Market.Props memory market, 1934 | | MarketPrices memory prices, 1935 | | bool isLong 1936 | * | ) internal view { 1937 | | // poolUsd is used instead of pool amount as the indexToken may not match the longToken 1938 | | // additionally, the shortToken may not be a stablecoin 1939 | * | uint256 poolUsd = getPoolUsdWithoutPnl( 1940 | * | dataStore, 1941 | * | market, 1942 | * | prices, 1943 | * | isLong, 1944 | * | false 1945 | | ); 1946 | * | uint256 reserveFactor = getReserveFactor( 1947 | * | dataStore, 1948 | * | market.marketToken, 1949 | * | isLong 1950 | | ); 1951 | * | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor); 1952 | | 1953 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong); 1954 | | 1955 | * | if (reservedUsd > maxReservedUsd) { 1956 | * | revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd); 1957 | | } 1958 | | } 1959 | | 1960 | | // @dev validate that the amount of tokens required to be reserved for open interest 1961 | | // is below the configured threshold 1962 | | // @param dataStore DataStore 1963 | | // @param market the market values 1964 | | // @param prices the prices of the market tokens 1965 | | // @param isLong whether to check the long or short side 1966 | * | function validateOpenInterestReserve( 1967 | | DataStore dataStore, 1968 | | Market.Props memory market, 1969 | | MarketPrices memory prices, 1970 | | bool isLong 1971 | * | ) internal view { 1972 | | // poolUsd is used instead of pool amount as the indexToken may not match the longToken 1973 | | // additionally, the shortToken may not be a stablecoin 1974 | * | uint256 poolUsd = getPoolUsdWithoutPnl( 1975 | * | dataStore, 1976 | * | market, 1977 | * | prices, 1978 | * | isLong, 1979 | * | false 1980 | | ); 1981 | * | uint256 reserveFactor = getOpenInterestReserveFactor( 1982 | * | dataStore, 1983 | * | market.marketToken, 1984 | * | isLong 1985 | | ); 1986 | * | uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor); 1987 | | 1988 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong); 1989 | | 1990 | * | if (reservedUsd > maxReservedUsd) { 1991 | | revert Errors.InsufficientReserveForOpenInterest( 1992 | | reservedUsd, 1993 | | maxReservedUsd 1994 | | ); 1995 | | } 1996 | | } 1997 | | 1998 | | // @dev update the swap impact pool amount, if it is a positive impact amount 1999 | | // cap the impact amount to the amount available in the swap impact pool 2000 | | // @param dataStore DataStore 2001 | | // @param eventEmitter EventEmitter 2002 | | // @param market the market to apply to 2003 | | // @param token the token to apply to 2004 | | // @param tokenPrice the price of the token 2005 | | // @param priceImpactUsd the USD price impact 2006 | * | function applySwapImpactWithCap( 2007 | | DataStore dataStore, 2008 | | EventEmitter eventEmitter, 2009 | | address market, 2010 | | address token, 2011 | | Price.Props memory tokenPrice, 2012 | | int256 priceImpactUsd 2013 | * | ) internal returns (int256, uint256) { 2014 | * | ( 2015 | * | int256 impactAmount, 2016 | * | uint256 cappedDiffUsd 2017 | * | ) = getSwapImpactAmountWithCap( 2018 | * | dataStore, 2019 | * | market, 2020 | * | token, 2021 | * | tokenPrice, 2022 | * | priceImpactUsd 2023 | | ); 2024 | | 2025 | | // if there is a positive impact, the impact pool amount should be reduced 2026 | | // if there is a negative impact, the impact pool amount should be increased 2027 | * | applyDeltaToSwapImpactPool( 2028 | * | dataStore, 2029 | * | eventEmitter, 2030 | * | market, 2031 | * | token, 2032 | * | -impactAmount 2033 | | ); 2034 | | 2035 | * | return (impactAmount, cappedDiffUsd); 2036 | | } 2037 | | 2038 | * | function getSwapImpactAmountWithCap( 2039 | | DataStore dataStore, 2040 | | address market, 2041 | | address token, 2042 | | Price.Props memory tokenPrice, 2043 | | int256 priceImpactUsd 2044 | * | ) internal view returns (int256, uint256) { 2045 | * | int256 impactAmount; 2046 | * | uint256 cappedDiffUsd; 2047 | | 2048 | * | if (priceImpactUsd > 0) { 2049 | | // positive impact: minimize impactAmount, use tokenPrice.max 2050 | | // round positive impactAmount down, this will be deducted from the swap impact pool for the user 2051 | | impactAmount = priceImpactUsd / tokenPrice.max.toInt256(); 2052 | | 2053 | | int256 maxImpactAmount = getSwapImpactPoolAmount( 2054 | | dataStore, 2055 | | market, 2056 | | token 2057 | | ).toInt256(); 2058 | | if (impactAmount > maxImpactAmount) { 2059 | | cappedDiffUsd = 2060 | | (impactAmount - maxImpactAmount).toUint256() * 2061 | | tokenPrice.max; 2062 | | impactAmount = maxImpactAmount; 2063 | | } 2064 | | } else { 2065 | | // negative impact: maximize impactAmount, use tokenPrice.min 2066 | | // round negative impactAmount up, this will be deducted from the user 2067 | * | impactAmount = Calc.roundUpMagnitudeDivision( 2068 | * | priceImpactUsd, 2069 | * | tokenPrice.min 2070 | | ); 2071 | | } 2072 | | 2073 | * | return (impactAmount, cappedDiffUsd); 2074 | | } 2075 | | 2076 | | // @dev get the funding amount to be deducted or distributed 2077 | | // 2078 | | // @param latestFundingAmountPerSize the latest funding amount per size 2079 | | // @param positionFundingAmountPerSize the funding amount per size for the position 2080 | | // @param positionSizeInUsd the position size in USD 2081 | | // @param roundUpMagnitude whether the round up the result 2082 | | // 2083 | | // @return fundingAmount 2084 | * | function getFundingAmount( 2085 | | uint256 latestFundingAmountPerSize, 2086 | | uint256 positionFundingAmountPerSize, 2087 | | uint256 positionSizeInUsd, 2088 | | bool roundUpMagnitude 2089 | * | ) internal pure returns (uint256) { 2090 | * | uint256 fundingDiffFactor = (latestFundingAmountPerSize - 2091 | * | positionFundingAmountPerSize); 2092 | | 2093 | | // a user could avoid paying funding fees by continually updating the position 2094 | | // before the funding fee becomes large enough to be chargeable 2095 | | // to avoid this, funding fee amounts should be rounded up 2096 | | // 2097 | | // this could lead to large additional charges if the token has a low number of decimals 2098 | | // or if the token's value is very high, so care should be taken to inform users of this 2099 | | // 2100 | | // if the calculation is for the claimable amount, the amount should be rounded down instead 2101 | | 2102 | | // divide the result by Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT as the fundingAmountPerSize values 2103 | | // are stored based on FLOAT_PRECISION_SQRT values 2104 | * | return 2105 | * | Precision.mulDiv( 2106 | * | positionSizeInUsd, 2107 | * | fundingDiffFactor, 2108 | * | Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT, 2109 | * | roundUpMagnitude 2110 | | ); 2111 | | } 2112 | | 2113 | | // @dev get the borrowing fees for a position, assumes that cumulativeBorrowingFactor 2114 | | // has already been updated to the latest value 2115 | | // @param dataStore DataStore 2116 | | // @param position Position.Props 2117 | | // @return the borrowing fees for a position 2118 | * | function getBorrowingFees( 2119 | | DataStore dataStore, 2120 | | Position.Props memory position 2121 | * | ) internal view returns (uint256) { 2122 | * | uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor( 2123 | * | dataStore, 2124 | * | position.market(), 2125 | * | position.isLong() 2126 | | ); 2127 | * | if (position.borrowingFactor() > cumulativeBorrowingFactor) { 2128 | | revert Errors.UnexpectedBorrowingFactor( 2129 | | position.borrowingFactor(), 2130 | | cumulativeBorrowingFactor 2131 | | ); 2132 | | } 2133 | * | uint256 diffFactor = cumulativeBorrowingFactor - 2134 | * | position.borrowingFactor(); 2135 | * | return Precision.applyFactor(position.sizeInUsd(), diffFactor); 2136 | | } 2137 | | 2138 | | // @dev get the borrowing fees for a position by calculating the latest cumulativeBorrowingFactor 2139 | | // @param dataStore DataStore 2140 | | // @param position Position.Props 2141 | | // @param market the position's market 2142 | | // @param prices the prices of the market tokens 2143 | | // @return the borrowing fees for a position 2144 | * | function getNextBorrowingFees( 2145 | | DataStore dataStore, 2146 | | Position.Props memory position, 2147 | | Market.Props memory market, 2148 | | MarketPrices memory prices 2149 | * | ) internal view returns (uint256) { 2150 | * | ( 2151 | * | uint256 nextCumulativeBorrowingFactor /* uint256 delta */, 2152 | | 2153 | * | ) = getNextCumulativeBorrowingFactor( 2154 | * | dataStore, 2155 | * | market, 2156 | * | prices, 2157 | * | position.isLong() 2158 | | ); 2159 | | 2160 | * | if (position.borrowingFactor() > nextCumulativeBorrowingFactor) { 2161 | | revert Errors.UnexpectedBorrowingFactor( 2162 | | position.borrowingFactor(), 2163 | | nextCumulativeBorrowingFactor 2164 | | ); 2165 | | } 2166 | * | uint256 diffFactor = nextCumulativeBorrowingFactor - 2167 | * | position.borrowingFactor(); 2168 | * | return Precision.applyFactor(position.sizeInUsd(), diffFactor); 2169 | | } 2170 | | 2171 | | // @dev get the total reserved USD required for positions 2172 | | // @param market the market to check 2173 | | // @param prices the prices of the market tokens 2174 | | // @param isLong whether to get the value for the long or short side 2175 | * | function getReservedUsd( 2176 | | DataStore dataStore, 2177 | | Market.Props memory market, 2178 | | MarketPrices memory prices, 2179 | | bool isLong 2180 | * | ) internal view returns (uint256) { 2181 | * | uint256 reservedUsd; 2182 | * | if (isLong) { 2183 | | // for longs calculate the reserved USD based on the open interest and current indexTokenPrice 2184 | | // this works well for e.g. an ETH / USD market with long collateral token as WETH 2185 | | // the available amount to be reserved would scale with the price of ETH 2186 | | // this also works for e.g. a SOL / USD market with long collateral token as WETH 2187 | | // if the price of SOL increases more than the price of ETH, additional amounts would be 2188 | | // automatically reserved 2189 | * | uint256 openInterestInTokens = getOpenInterestInTokens( 2190 | * | dataStore, 2191 | * | market, 2192 | * | isLong 2193 | | ); 2194 | * | reservedUsd = openInterestInTokens * prices.indexTokenPrice.max; 2195 | | } else { 2196 | | // for shorts use the open interest as the reserved USD value 2197 | | // this works well for e.g. an ETH / USD market with short collateral token as USDC 2198 | | // the available amount to be reserved would not change with the price of ETH 2199 | * | reservedUsd = getOpenInterest(dataStore, market, isLong); 2200 | | } 2201 | | 2202 | * | return reservedUsd; 2203 | | } 2204 | | 2205 | | // @dev get the virtual inventory for swaps 2206 | | // @param dataStore DataStore 2207 | | // @param market the market to check 2208 | | // @return returns (has virtual inventory, virtual long token inventory, virtual short token inventory) 2209 | * | function getVirtualInventoryForSwaps( 2210 | | DataStore dataStore, 2211 | | address market 2212 | * | ) internal view returns (bool, uint256, uint256) { 2213 | * | bytes32 virtualMarketId = dataStore.getBytes32( 2214 | * | Keys.virtualMarketIdKey(market) 2215 | | ); 2216 | * | if (virtualMarketId == bytes32(0)) { 2217 | * | return (false, 0, 0); 2218 | | } 2219 | | 2220 | | return ( 2221 | | true, 2222 | | dataStore.getUint( 2223 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, true) 2224 | | ), 2225 | | dataStore.getUint( 2226 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, false) 2227 | | ) 2228 | | ); 2229 | | } 2230 | | 2231 | | function getIsLongToken( 2232 | | Market.Props memory market, 2233 | | address token 2234 | | ) internal pure returns (bool) { 2235 | | if (token != market.longToken && token != market.shortToken) { 2236 | | revert Errors.UnexpectedTokenForVirtualInventory( 2237 | | token, 2238 | | market.marketToken 2239 | | ); 2240 | | } 2241 | | 2242 | | return token == market.longToken; 2243 | | } 2244 | | 2245 | | // @dev get the virtual inventory for positions 2246 | | // @param dataStore DataStore 2247 | | // @param token the token to check 2248 | * | function getVirtualInventoryForPositions( 2249 | | DataStore dataStore, 2250 | | address token 2251 | * | ) internal view returns (bool, int256) { 2252 | * | bytes32 virtualTokenId = dataStore.getBytes32( 2253 | * | Keys.virtualTokenIdKey(token) 2254 | | ); 2255 | * | if (virtualTokenId == bytes32(0)) { 2256 | * | return (false, 0); 2257 | | } 2258 | | 2259 | | return ( 2260 | | true, 2261 | | dataStore.getInt( 2262 | | Keys.virtualInventoryForPositionsKey(virtualTokenId) 2263 | | ) 2264 | | ); 2265 | | } 2266 | | 2267 | | // @dev update the virtual inventory for swaps 2268 | | // @param dataStore DataStore 2269 | | // @param marketAddress the market to update 2270 | | // @param token the token to update 2271 | | // @param delta the update amount 2272 | * | function applyDeltaToVirtualInventoryForSwaps( 2273 | | DataStore dataStore, 2274 | | EventEmitter eventEmitter, 2275 | | Market.Props memory market, 2276 | | address token, 2277 | | int256 delta 2278 | * | ) internal returns (bool, uint256) { 2279 | * | bytes32 virtualMarketId = dataStore.getBytes32( 2280 | * | Keys.virtualMarketIdKey(market.marketToken) 2281 | | ); 2282 | * | if (virtualMarketId == bytes32(0)) { 2283 | * | return (false, 0); 2284 | | } 2285 | | 2286 | | bool isLongToken = getIsLongToken(market, token); 2287 | | 2288 | | uint256 nextValue = dataStore.applyBoundedDeltaToUint( 2289 | | Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken), 2290 | | delta 2291 | | ); 2292 | | 2293 | | MarketEventUtils.emitVirtualSwapInventoryUpdated( 2294 | | eventEmitter, 2295 | | market.marketToken, 2296 | | isLongToken, 2297 | | virtualMarketId, 2298 | | delta, 2299 | | nextValue 2300 | | ); 2301 | | 2302 | | return (true, nextValue); 2303 | | } 2304 | | 2305 | | // @dev update the virtual inventory for positions 2306 | | // @param dataStore DataStore 2307 | | // @param eventEmitter EventEmitter 2308 | | // @param token the token to update 2309 | | // @param delta the update amount 2310 | * | function applyDeltaToVirtualInventoryForPositions( 2311 | | DataStore dataStore, 2312 | | EventEmitter eventEmitter, 2313 | | address token, 2314 | | int256 delta 2315 | * | ) internal returns (bool, int256) { 2316 | * | bytes32 virtualTokenId = dataStore.getBytes32( 2317 | * | Keys.virtualTokenIdKey(token) 2318 | | ); 2319 | * | if (virtualTokenId == bytes32(0)) { 2320 | * | return (false, 0); 2321 | | } 2322 | | 2323 | | int256 nextValue = dataStore.applyDeltaToInt( 2324 | | Keys.virtualInventoryForPositionsKey(virtualTokenId), 2325 | | delta 2326 | | ); 2327 | | 2328 | | MarketEventUtils.emitVirtualPositionInventoryUpdated( 2329 | | eventEmitter, 2330 | | token, 2331 | | virtualTokenId, 2332 | | delta, 2333 | | nextValue 2334 | | ); 2335 | | 2336 | | return (true, nextValue); 2337 | | } 2338 | | 2339 | | // @dev get the open interest of a market 2340 | | // @param dataStore DataStore 2341 | | // @param market the market to check 2342 | | // @param longToken the long token of the market 2343 | | // @param shortToken the short token of the market 2344 | | function getOpenInterest( 2345 | | DataStore dataStore, 2346 | | Market.Props memory market 2347 | | ) internal view returns (uint256) { 2348 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true); 2349 | | uint256 shortOpenInterest = getOpenInterest(dataStore, market, false); 2350 | | 2351 | | return longOpenInterest + shortOpenInterest; 2352 | | } 2353 | | 2354 | | // @dev get either the long or short open interest for a market 2355 | | // @param dataStore DataStore 2356 | | // @param market the market to check 2357 | | // @param longToken the long token of the market 2358 | | // @param shortToken the short token of the market 2359 | | // @param isLong whether to get the long or short open interest 2360 | | // @return the long or short open interest for a market 2361 | * | function getOpenInterest( 2362 | | DataStore dataStore, 2363 | | Market.Props memory market, 2364 | | bool isLong 2365 | * | ) internal view returns (uint256) { 2366 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 2367 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest( 2368 | * | dataStore, 2369 | * | market.marketToken, 2370 | * | market.longToken, 2371 | * | isLong, 2372 | * | divisor 2373 | | ); 2374 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest( 2375 | * | dataStore, 2376 | * | market.marketToken, 2377 | * | market.shortToken, 2378 | * | isLong, 2379 | * | divisor 2380 | | ); 2381 | | 2382 | * | return 2383 | * | openInterestUsingLongTokenAsCollateral + 2384 | * | openInterestUsingShortTokenAsCollateral; 2385 | | } 2386 | | 2387 | | // @dev the long and short open interest for a market based on the collateral token used 2388 | | // @param dataStore DataStore 2389 | | // @param market the market to check 2390 | | // @param collateralToken the collateral token to check 2391 | | // @param isLong whether to check the long or short side 2392 | * | function getOpenInterest( 2393 | | DataStore dataStore, 2394 | | address market, 2395 | | address collateralToken, 2396 | | bool isLong, 2397 | | uint256 divisor 2398 | * | ) internal view returns (uint256) { 2399 | * | return 2400 | * | dataStore.getUint( 2401 | * | Keys.openInterestKey(market, collateralToken, isLong) 2402 | * | ) / divisor; 2403 | | } 2404 | | 2405 | | // this is used to divide the values of getPoolAmount and getOpenInterest 2406 | | // if the longToken and shortToken are the same, then these values have to be divided by two 2407 | | // to avoid double counting 2408 | * | function getPoolDivisor( 2409 | | address longToken, 2410 | | address shortToken 2411 | * | ) internal pure returns (uint256) { 2412 | * | return longToken == shortToken ? 2 : 1; 2413 | | } 2414 | | 2415 | | // @dev the long and short open interest in tokens for a market 2416 | | // @param dataStore DataStore 2417 | | // @param market the market to check 2418 | | // @param longToken the long token of the market 2419 | | // @param shortToken the short token of the market 2420 | | // @param isLong whether to check the long or short side 2421 | * | function getOpenInterestInTokens( 2422 | | DataStore dataStore, 2423 | | Market.Props memory market, 2424 | | bool isLong 2425 | * | ) internal view returns (uint256) { 2426 | * | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 2427 | * | uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens( 2428 | * | dataStore, 2429 | * | market.marketToken, 2430 | * | market.longToken, 2431 | * | isLong, 2432 | * | divisor 2433 | | ); 2434 | * | uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens( 2435 | * | dataStore, 2436 | * | market.marketToken, 2437 | * | market.shortToken, 2438 | * | isLong, 2439 | * | divisor 2440 | | ); 2441 | | 2442 | * | return 2443 | * | openInterestUsingLongTokenAsCollateral + 2444 | * | openInterestUsingShortTokenAsCollateral; 2445 | | } 2446 | | 2447 | | // @dev the long and short open interest in tokens for a market based on the collateral token used 2448 | | // @param dataStore DataStore 2449 | | // @param market the market to check 2450 | | // @param collateralToken the collateral token to check 2451 | | // @param isLong whether to check the long or short side 2452 | * | function getOpenInterestInTokens( 2453 | | DataStore dataStore, 2454 | | address market, 2455 | | address collateralToken, 2456 | | bool isLong, 2457 | | uint256 divisor 2458 | * | ) internal view returns (uint256) { 2459 | * | return 2460 | * | dataStore.getUint( 2461 | * | Keys.openInterestInTokensKey(market, collateralToken, isLong) 2462 | * | ) / divisor; 2463 | | } 2464 | | 2465 | | // @dev get the sum of open interest and pnl for a market 2466 | | // getOpenInterestInTokens * tokenPrice would not reflect pending positive pnl 2467 | | // for short positions, so getOpenInterestWithPnl should be used if that info is needed 2468 | | // @param dataStore DataStore 2469 | | // @param market the market to check 2470 | | // @param longToken the long token of the market 2471 | | // @param shortToken the short token of the market 2472 | | // @param indexTokenPrice the price of the index token 2473 | | // @param isLong whether to check the long or short side 2474 | | // @param maximize whether to maximize or minimize the value 2475 | | // @return the sum of open interest and pnl for a market 2476 | | function getOpenInterestWithPnl( 2477 | | DataStore dataStore, 2478 | | Market.Props memory market, 2479 | | Price.Props memory indexTokenPrice, 2480 | | bool isLong, 2481 | | bool maximize 2482 | | ) internal view returns (int256) { 2483 | | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 2484 | | int256 pnl = getPnl( 2485 | | dataStore, 2486 | | market, 2487 | | indexTokenPrice, 2488 | | isLong, 2489 | | maximize 2490 | | ); 2491 | | return Calc.sumReturnInt256(openInterest, pnl); 2492 | | } 2493 | | 2494 | | // @dev get the max position impact factor for decreasing position 2495 | | // @param dataStore DataStore 2496 | | // @param market the market to check 2497 | | // @param isPositive whether the price impact is positive or negative 2498 | * | function getMaxPositionImpactFactor( 2499 | | DataStore dataStore, 2500 | | address market, 2501 | | bool isPositive 2502 | * | ) internal view returns (uint256) { 2503 | * | ( 2504 | * | uint256 maxPositiveImpactFactor, 2505 | * | uint256 maxNegativeImpactFactor 2506 | * | ) = getMaxPositionImpactFactors(dataStore, market); 2507 | | 2508 | * | return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor; 2509 | | } 2510 | | 2511 | * | function getMaxPositionImpactFactors( 2512 | | DataStore dataStore, 2513 | | address market 2514 | * | ) internal view returns (uint256, uint256) { 2515 | * | uint256 maxPositiveImpactFactor = dataStore.getUint( 2516 | * | Keys.maxPositionImpactFactorKey(market, true) 2517 | | ); 2518 | * | uint256 maxNegativeImpactFactor = dataStore.getUint( 2519 | * | Keys.maxPositionImpactFactorKey(market, false) 2520 | | ); 2521 | | 2522 | * | if (maxPositiveImpactFactor > maxNegativeImpactFactor) { 2523 | | maxPositiveImpactFactor = maxNegativeImpactFactor; 2524 | | } 2525 | | 2526 | * | return (maxPositiveImpactFactor, maxNegativeImpactFactor); 2527 | | } 2528 | | 2529 | | // @dev get the max position impact factor for liquidations 2530 | | // @param dataStore DataStore 2531 | | // @param market the market to check 2532 | | function getMaxPositionImpactFactorForLiquidations( 2533 | | DataStore dataStore, 2534 | | address market 2535 | | ) internal view returns (uint256) { 2536 | | return 2537 | | dataStore.getUint( 2538 | | Keys.maxPositionImpactFactorForLiquidationsKey(market) 2539 | | ); 2540 | | } 2541 | | 2542 | | // @dev get the min collateral factor 2543 | | // @param dataStore DataStore 2544 | | // @param market the market to check 2545 | * | function getMinCollateralFactor( 2546 | | DataStore dataStore, 2547 | | address market 2548 | * | ) internal view returns (uint256) { 2549 | * | return dataStore.getUint(Keys.minCollateralFactorKey(market)); 2550 | | } 2551 | | 2552 | | // @dev get the min collateral factor for open interest multiplier 2553 | | // @param dataStore DataStore 2554 | | // @param market the market to check 2555 | | // @param isLong whether it is for the long or short side 2556 | * | function getMinCollateralFactorForOpenInterestMultiplier( 2557 | | DataStore dataStore, 2558 | | address market, 2559 | | bool isLong 2560 | * | ) internal view returns (uint256) { 2561 | * | return 2562 | * | dataStore.getUint( 2563 | * | Keys.minCollateralFactorForOpenInterestMultiplierKey( 2564 | * | market, 2565 | * | isLong 2566 | | ) 2567 | | ); 2568 | | } 2569 | | 2570 | | // @dev get the min collateral factor for open interest 2571 | | // @param dataStore DataStore 2572 | | // @param market the market to check 2573 | | // @param longToken the long token of the market 2574 | | // @param shortToken the short token of the market 2575 | | // @param openInterestDelta the change in open interest 2576 | | // @param isLong whether it is for the long or short side 2577 | * | function getMinCollateralFactorForOpenInterest( 2578 | | DataStore dataStore, 2579 | | Market.Props memory market, 2580 | | int256 openInterestDelta, 2581 | | bool isLong 2582 | * | ) internal view returns (uint256) { 2583 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 2584 | * | openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta); 2585 | * | uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier( 2586 | * | dataStore, 2587 | * | market.marketToken, 2588 | * | isLong 2589 | | ); 2590 | * | return Precision.applyFactor(openInterest, multiplierFactor); 2591 | | } 2592 | | 2593 | | // @dev get the total amount of position collateral for a market 2594 | | // @param dataStore DataStore 2595 | | // @param market the market to check 2596 | | // @param collateralToken the collateralToken to check 2597 | | // @param isLong whether to get the value for longs or shorts 2598 | | // @return the total amount of position collateral for a market 2599 | * | function getCollateralSum( 2600 | | DataStore dataStore, 2601 | | address market, 2602 | | address collateralToken, 2603 | | bool isLong, 2604 | | uint256 divisor 2605 | * | ) internal view returns (uint256) { 2606 | * | return 2607 | * | dataStore.getUint( 2608 | * | Keys.collateralSumKey(market, collateralToken, isLong) 2609 | * | ) / divisor; 2610 | | } 2611 | | 2612 | | // @dev get the reserve factor for a market 2613 | | // @param dataStore DataStore 2614 | | // @param market the market to check 2615 | | // @param isLong whether to get the value for longs or shorts 2616 | | // @return the reserve factor for a market 2617 | * | function getReserveFactor( 2618 | | DataStore dataStore, 2619 | | address market, 2620 | | bool isLong 2621 | * | ) internal view returns (uint256) { 2622 | * | return dataStore.getUint(Keys.reserveFactorKey(market, isLong)); 2623 | | } 2624 | | 2625 | | // @dev get the open interest reserve factor for a market 2626 | | // @param dataStore DataStore 2627 | | // @param market the market to check 2628 | | // @param isLong whether to get the value for longs or shorts 2629 | | // @return the open interest reserve factor for a market 2630 | * | function getOpenInterestReserveFactor( 2631 | | DataStore dataStore, 2632 | | address market, 2633 | | bool isLong 2634 | * | ) internal view returns (uint256) { 2635 | * | return 2636 | * | dataStore.getUint( 2637 | * | Keys.openInterestReserveFactorKey(market, isLong) 2638 | | ); 2639 | | } 2640 | | 2641 | | // @dev get the max pnl factor for a market 2642 | | // @param dataStore DataStore 2643 | | // @param pnlFactorType the type of the pnl factor 2644 | | // @param market the market to check 2645 | | // @param isLong whether to get the value for longs or shorts 2646 | | // @return the max pnl factor for a market 2647 | * | function getMaxPnlFactor( 2648 | | DataStore dataStore, 2649 | | bytes32 pnlFactorType, 2650 | | address market, 2651 | | bool isLong 2652 | * | ) internal view returns (uint256) { 2653 | * | return 2654 | * | dataStore.getUint( 2655 | * | Keys.maxPnlFactorKey(pnlFactorType, market, isLong) 2656 | | ); 2657 | | } 2658 | | 2659 | | // @dev get the min pnl factor after ADL 2660 | | // @param dataStore DataStore 2661 | | // @param market the market to check 2662 | | // @param isLong whether to check the long or short side 2663 | * | function getMinPnlFactorAfterAdl( 2664 | | DataStore dataStore, 2665 | | address market, 2666 | | bool isLong 2667 | * | ) internal view returns (uint256) { 2668 | * | return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong)); 2669 | | } 2670 | | 2671 | | // @dev get the funding factor for a market 2672 | | // @param dataStore DataStore 2673 | | // @param market the market to check 2674 | | // @return the funding factor for a market 2675 | * | function getFundingFactor( 2676 | | DataStore dataStore, 2677 | | address market 2678 | * | ) internal view returns (uint256) { 2679 | * | return dataStore.getUint(Keys.fundingFactorKey(market)); 2680 | | } 2681 | | 2682 | | // @dev get the saved funding factor for a market 2683 | | // @param dataStore DataStore 2684 | | // @param market the market to check 2685 | | // @return the saved funding factor for a market 2686 | | function getSavedFundingFactorPerSecond( 2687 | | DataStore dataStore, 2688 | | address market 2689 | | ) internal view returns (int256) { 2690 | | return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market)); 2691 | | } 2692 | | 2693 | | // @dev set the saved funding factor 2694 | | // @param dataStore DataStore 2695 | | // @param market the market to set the funding factor for 2696 | * | function setSavedFundingFactorPerSecond( 2697 | | DataStore dataStore, 2698 | | address market, 2699 | | int256 value 2700 | * | ) internal returns (int256) { 2701 | * | return 2702 | * | dataStore.setInt( 2703 | * | Keys.savedFundingFactorPerSecondKey(market), 2704 | * | value 2705 | | ); 2706 | | } 2707 | | 2708 | | // @dev get the funding exponent factor for a market 2709 | | // @param dataStore DataStore 2710 | | // @param market the market to check 2711 | | // @return the funding exponent factor for a market 2712 | * | function getFundingExponentFactor( 2713 | | DataStore dataStore, 2714 | | address market 2715 | * | ) internal view returns (uint256) { 2716 | * | return dataStore.getUint(Keys.fundingExponentFactorKey(market)); 2717 | | } 2718 | | 2719 | | // @dev get the funding fee amount per size for a market 2720 | | // @param dataStore DataStore 2721 | | // @param market the market to check 2722 | | // @param collateralToken the collateralToken to check 2723 | | // @param isLong whether to check the long or short size 2724 | | // @return the funding fee amount per size for a market based on collateralToken 2725 | * | function getFundingFeeAmountPerSize( 2726 | | DataStore dataStore, 2727 | | address market, 2728 | | address collateralToken, 2729 | | bool isLong 2730 | * | ) internal view returns (uint256) { 2731 | * | return 2732 | * | dataStore.getUint( 2733 | * | Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong) 2734 | | ); 2735 | | } 2736 | | 2737 | | // @dev get the claimable funding amount per size for a market 2738 | | // @param dataStore DataStore 2739 | | // @param market the market to check 2740 | | // @param collateralToken the collateralToken to check 2741 | | // @param isLong whether to check the long or short size 2742 | | // @return the claimable funding amount per size for a market based on collateralToken 2743 | * | function getClaimableFundingAmountPerSize( 2744 | | DataStore dataStore, 2745 | | address market, 2746 | | address collateralToken, 2747 | | bool isLong 2748 | * | ) internal view returns (uint256) { 2749 | * | return 2750 | * | dataStore.getUint( 2751 | * | Keys.claimableFundingAmountPerSizeKey( 2752 | * | market, 2753 | * | collateralToken, 2754 | * | isLong 2755 | | ) 2756 | | ); 2757 | | } 2758 | | 2759 | | // @dev apply delta to the funding fee amount per size for a market 2760 | | // @param dataStore DataStore 2761 | | // @param market the market to set 2762 | | // @param collateralToken the collateralToken to set 2763 | | // @param isLong whether to set it for the long or short side 2764 | | // @param delta the delta to increment by 2765 | * | function applyDeltaToFundingFeeAmountPerSize( 2766 | | DataStore dataStore, 2767 | | EventEmitter eventEmitter, 2768 | | address market, 2769 | | address collateralToken, 2770 | | bool isLong, 2771 | | uint256 delta 2772 | * | ) internal { 2773 | * | if (delta == 0) { 2774 | * | return; 2775 | | } 2776 | | 2777 | * | uint256 nextValue = dataStore.applyDeltaToUint( 2778 | * | Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong), 2779 | * | delta 2780 | | ); 2781 | | 2782 | * | MarketEventUtils.emitFundingFeeAmountPerSizeUpdated( 2783 | * | eventEmitter, 2784 | * | market, 2785 | * | collateralToken, 2786 | * | isLong, 2787 | * | delta, 2788 | * | nextValue 2789 | | ); 2790 | | } 2791 | | 2792 | | // @dev apply delta to the claimable funding amount per size for a market 2793 | | // @param dataStore DataStore 2794 | | // @param market the market to set 2795 | | // @param collateralToken the collateralToken to set 2796 | | // @param isLong whether to set it for the long or short side 2797 | | // @param delta the delta to increment by 2798 | * | function applyDeltaToClaimableFundingAmountPerSize( 2799 | | DataStore dataStore, 2800 | | EventEmitter eventEmitter, 2801 | | address market, 2802 | | address collateralToken, 2803 | | bool isLong, 2804 | | uint256 delta 2805 | * | ) internal { 2806 | * | if (delta == 0) { 2807 | * | return; 2808 | | } 2809 | | 2810 | * | uint256 nextValue = dataStore.applyDeltaToUint( 2811 | * | Keys.claimableFundingAmountPerSizeKey( 2812 | * | market, 2813 | * | collateralToken, 2814 | * | isLong 2815 | | ), 2816 | * | delta 2817 | | ); 2818 | | 2819 | * | MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated( 2820 | * | eventEmitter, 2821 | * | market, 2822 | * | collateralToken, 2823 | * | isLong, 2824 | * | delta, 2825 | * | nextValue 2826 | | ); 2827 | | } 2828 | | 2829 | | // @dev get the number of seconds since funding was updated for a market 2830 | | // @param market the market to check 2831 | | // @return the number of seconds since funding was updated for a market 2832 | * | function getSecondsSinceFundingUpdated( 2833 | | DataStore dataStore, 2834 | | address market 2835 | * | ) internal view returns (uint256) { 2836 | * | uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market)); 2837 | * | if (updatedAt == 0) { 2838 | | return 0; 2839 | | } 2840 | * | return Chain.currentTimestamp() - updatedAt; 2841 | | } 2842 | | 2843 | | // @dev get the borrowing factor for a market 2844 | | // @param dataStore DataStore 2845 | | // @param market the market to check 2846 | | // @param isLong whether to check the long or short side 2847 | | // @return the borrowing factor for a market 2848 | * | function getBorrowingFactor( 2849 | | DataStore dataStore, 2850 | | address market, 2851 | | bool isLong 2852 | * | ) internal view returns (uint256) { 2853 | * | return dataStore.getUint(Keys.borrowingFactorKey(market, isLong)); 2854 | | } 2855 | | 2856 | * | function getOptimalUsageFactor( 2857 | | DataStore dataStore, 2858 | | address market, 2859 | | bool isLong 2860 | * | ) internal view returns (uint256) { 2861 | * | return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong)); 2862 | | } 2863 | | 2864 | | // @dev get the borrowing exponent factor for a market 2865 | | // @param dataStore DataStore 2866 | | // @param market the market to check 2867 | | // @param isLong whether to check the long or short side 2868 | | // @return the borrowing exponent factor for a market 2869 | * | function getBorrowingExponentFactor( 2870 | | DataStore dataStore, 2871 | | address market, 2872 | | bool isLong 2873 | * | ) internal view returns (uint256) { 2874 | * | return 2875 | * | dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong)); 2876 | | } 2877 | | 2878 | | // @dev get the cumulative borrowing factor for a market 2879 | | // @param dataStore DataStore 2880 | | // @param market the market to check 2881 | | // @param isLong whether to check the long or short side 2882 | | // @return the cumulative borrowing factor for a market 2883 | * | function getCumulativeBorrowingFactor( 2884 | | DataStore dataStore, 2885 | | address market, 2886 | | bool isLong 2887 | * | ) internal view returns (uint256) { 2888 | * | return 2889 | * | dataStore.getUint( 2890 | * | Keys.cumulativeBorrowingFactorKey(market, isLong) 2891 | | ); 2892 | | } 2893 | | 2894 | | // @dev increase the cumulative borrowing factor 2895 | | // @param dataStore DataStore 2896 | | // @param eventEmitter EventEmitter 2897 | | // @param market the market to increment the borrowing factor for 2898 | | // @param isLong whether to increment the long or short side 2899 | | // @param delta the increase amount 2900 | * | function incrementCumulativeBorrowingFactor( 2901 | | DataStore dataStore, 2902 | | EventEmitter eventEmitter, 2903 | | address market, 2904 | | bool isLong, 2905 | | uint256 delta 2906 | * | ) internal { 2907 | * | uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint( 2908 | * | Keys.cumulativeBorrowingFactorKey(market, isLong), 2909 | * | delta 2910 | | ); 2911 | | 2912 | * | MarketEventUtils.emitBorrowingFactorUpdated( 2913 | * | eventEmitter, 2914 | * | market, 2915 | * | isLong, 2916 | * | delta, 2917 | * | nextCumulativeBorrowingFactor 2918 | | ); 2919 | | } 2920 | | 2921 | | // @dev get the timestamp of when the cumulative borrowing factor was last updated 2922 | | // @param dataStore DataStore 2923 | | // @param market the market to check 2924 | | // @param isLong whether to check the long or short side 2925 | | // @return the timestamp of when the cumulative borrowing factor was last updated 2926 | * | function getCumulativeBorrowingFactorUpdatedAt( 2927 | | DataStore dataStore, 2928 | | address market, 2929 | | bool isLong 2930 | * | ) internal view returns (uint256) { 2931 | * | return 2932 | * | dataStore.getUint( 2933 | * | Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong) 2934 | | ); 2935 | | } 2936 | | 2937 | | // @dev get the number of seconds since the cumulative borrowing factor was last updated 2938 | | // @param dataStore DataStore 2939 | | // @param market the market to check 2940 | | // @param isLong whether to check the long or short side 2941 | | // @return the number of seconds since the cumulative borrowing factor was last updated 2942 | * | function getSecondsSinceCumulativeBorrowingFactorUpdated( 2943 | | DataStore dataStore, 2944 | | address market, 2945 | | bool isLong 2946 | * | ) internal view returns (uint256) { 2947 | * | uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt( 2948 | * | dataStore, 2949 | * | market, 2950 | * | isLong 2951 | | ); 2952 | * | if (updatedAt == 0) { 2953 | * | return 0; 2954 | | } 2955 | * | return Chain.currentTimestamp() - updatedAt; 2956 | | } 2957 | | 2958 | | // @dev update the total borrowing amount after a position changes size 2959 | | // this is the sum of all position.borrowingFactor * position.sizeInUsd 2960 | | // @param dataStore DataStore 2961 | | // @param market the market to update 2962 | | // @param isLong whether to update the long or short side 2963 | | // @param prevPositionSizeInUsd the previous position size in USD 2964 | | // @param prevPositionBorrowingFactor the previous position borrowing factor 2965 | | // @param nextPositionSizeInUsd the next position size in USD 2966 | | // @param nextPositionBorrowingFactor the next position borrowing factor 2967 | * | function updateTotalBorrowing( 2968 | | DataStore dataStore, 2969 | | address market, 2970 | | bool isLong, 2971 | | uint256 prevPositionSizeInUsd, 2972 | | uint256 prevPositionBorrowingFactor, 2973 | | uint256 nextPositionSizeInUsd, 2974 | | uint256 nextPositionBorrowingFactor 2975 | * | ) internal { 2976 | * | uint256 totalBorrowing = getNextTotalBorrowing( 2977 | * | dataStore, 2978 | * | market, 2979 | * | isLong, 2980 | * | prevPositionSizeInUsd, 2981 | * | prevPositionBorrowingFactor, 2982 | * | nextPositionSizeInUsd, 2983 | * | nextPositionBorrowingFactor 2984 | | ); 2985 | | 2986 | * | setTotalBorrowing(dataStore, market, isLong, totalBorrowing); 2987 | | } 2988 | | 2989 | | // @dev get the next total borrowing amount after a position changes size 2990 | | // @param dataStore DataStore 2991 | | // @param market the market to check 2992 | | // @param isLong whether to check the long or short side 2993 | | // @param prevPositionSizeInUsd the previous position size in USD 2994 | | // @param prevPositionBorrowingFactor the previous position borrowing factor 2995 | | // @param nextPositionSizeInUsd the next position size in USD 2996 | | // @param nextPositionBorrowingFactor the next position borrowing factor 2997 | * | function getNextTotalBorrowing( 2998 | | DataStore dataStore, 2999 | | address market, 3000 | | bool isLong, 3001 | | uint256 prevPositionSizeInUsd, 3002 | | uint256 prevPositionBorrowingFactor, 3003 | | uint256 nextPositionSizeInUsd, 3004 | | uint256 nextPositionBorrowingFactor 3005 | * | ) internal view returns (uint256) { 3006 | * | uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong); 3007 | * | totalBorrowing -= Precision.applyFactor( 3008 | * | prevPositionSizeInUsd, 3009 | * | prevPositionBorrowingFactor 3010 | | ); 3011 | * | totalBorrowing += Precision.applyFactor( 3012 | * | nextPositionSizeInUsd, 3013 | * | nextPositionBorrowingFactor 3014 | | ); 3015 | | 3016 | * | return totalBorrowing; 3017 | | } 3018 | | 3019 | | // @dev get the next cumulative borrowing factor 3020 | | // @param dataStore DataStore 3021 | | // @param prices the prices of the market tokens 3022 | | // @param market the market to check 3023 | | // @param longToken the long token of the market 3024 | | // @param shortToken the short token of the market 3025 | | // @param isLong whether to check the long or short side 3026 | * | function getNextCumulativeBorrowingFactor( 3027 | | DataStore dataStore, 3028 | | Market.Props memory market, 3029 | | MarketPrices memory prices, 3030 | | bool isLong 3031 | * | ) internal view returns (uint256, uint256) { 3032 | * | uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated( 3033 | * | dataStore, 3034 | * | market.marketToken, 3035 | * | isLong 3036 | | ); 3037 | * | uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond( 3038 | * | dataStore, 3039 | * | market, 3040 | * | prices, 3041 | * | isLong 3042 | | ); 3043 | | 3044 | * | uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor( 3045 | * | dataStore, 3046 | * | market.marketToken, 3047 | * | isLong 3048 | | ); 3049 | | 3050 | * | uint256 delta = durationInSeconds * borrowingFactorPerSecond; 3051 | * | uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + 3052 | * | delta; 3053 | * | return (nextCumulativeBorrowingFactor, delta); 3054 | | } 3055 | | 3056 | | // @dev get the borrowing factor per second 3057 | | // @param dataStore DataStore 3058 | | // @param market the market to get the borrowing factor per second for 3059 | | // @param prices the prices of the market tokens 3060 | | // @param isLong whether to get the factor for the long or short side 3061 | * | function getBorrowingFactorPerSecond( 3062 | | DataStore dataStore, 3063 | | Market.Props memory market, 3064 | | MarketPrices memory prices, 3065 | | bool isLong 3066 | * | ) internal view returns (uint256) { 3067 | * | uint256 reservedUsd = getReservedUsd(dataStore, market, prices, isLong); 3068 | | 3069 | * | if (reservedUsd == 0) { 3070 | * | return 0; 3071 | | } 3072 | | 3073 | | // check if the borrowing fee for the smaller side should be skipped 3074 | | // if skipBorrowingFeeForSmallerSide is true, and the longOpenInterest is exactly the same as the shortOpenInterest 3075 | | // then the borrowing fee would be charged for both sides, this should be very rare 3076 | * | bool skipBorrowingFeeForSmallerSide = dataStore.getBool( 3077 | | Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE 3078 | | ); 3079 | * | if (skipBorrowingFeeForSmallerSide) { 3080 | | uint256 longOpenInterest = getOpenInterest(dataStore, market, true); 3081 | | uint256 shortOpenInterest = getOpenInterest( 3082 | | dataStore, 3083 | | market, 3084 | | false 3085 | | ); 3086 | | 3087 | | // if getting the borrowing factor for longs and if the longOpenInterest 3088 | | // is smaller than the shortOpenInterest, then return zero 3089 | | if (isLong && longOpenInterest < shortOpenInterest) { 3090 | | return 0; 3091 | | } 3092 | | 3093 | | // if getting the borrowing factor for shorts and if the shortOpenInterest 3094 | | // is smaller than the longOpenInterest, then return zero 3095 | | if (!isLong && shortOpenInterest < longOpenInterest) { 3096 | | return 0; 3097 | | } 3098 | | } 3099 | | 3100 | * | uint256 poolUsd = getPoolUsdWithoutPnl( 3101 | * | dataStore, 3102 | * | market, 3103 | * | prices, 3104 | * | isLong, 3105 | * | false 3106 | | ); 3107 | | 3108 | * | if (poolUsd == 0) { 3109 | | revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd(); 3110 | | } 3111 | | 3112 | * | uint256 optimalUsageFactor = getOptimalUsageFactor( 3113 | * | dataStore, 3114 | * | market.marketToken, 3115 | * | isLong 3116 | | ); 3117 | | 3118 | * | if (optimalUsageFactor != 0) { 3119 | | return 3120 | | getKinkBorrowingFactor( 3121 | | dataStore, 3122 | | market, 3123 | | isLong, 3124 | | reservedUsd, 3125 | | poolUsd, 3126 | | optimalUsageFactor 3127 | | ); 3128 | | } 3129 | | 3130 | * | uint256 borrowingExponentFactor = getBorrowingExponentFactor( 3131 | * | dataStore, 3132 | * | market.marketToken, 3133 | * | isLong 3134 | | ); 3135 | * | uint256 reservedUsdAfterExponent = Precision.applyExponentFactor( 3136 | * | reservedUsd, 3137 | * | borrowingExponentFactor 3138 | | ); 3139 | | 3140 | * | uint256 reservedUsdToPoolFactor = Precision.toFactor( 3141 | * | reservedUsdAfterExponent, 3142 | * | poolUsd 3143 | | ); 3144 | * | uint256 borrowingFactor = getBorrowingFactor( 3145 | * | dataStore, 3146 | * | market.marketToken, 3147 | * | isLong 3148 | | ); 3149 | | 3150 | * | return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor); 3151 | | } 3152 | | 3153 | | function getKinkBorrowingFactor( 3154 | | DataStore dataStore, 3155 | | Market.Props memory market, 3156 | | bool isLong, 3157 | | uint256 reservedUsd, 3158 | | uint256 poolUsd, 3159 | | uint256 optimalUsageFactor 3160 | | ) internal view returns (uint256) { 3161 | | uint256 usageFactor = getUsageFactor( 3162 | | dataStore, 3163 | | market, 3164 | | isLong, 3165 | | reservedUsd, 3166 | | poolUsd 3167 | | ); 3168 | | 3169 | | uint256 baseBorrowingFactor = dataStore.getUint( 3170 | | Keys.baseBorrowingFactorKey(market.marketToken, isLong) 3171 | | ); 3172 | | 3173 | | uint256 borrowingFactorPerSecond = Precision.applyFactor( 3174 | | usageFactor, 3175 | | baseBorrowingFactor 3176 | | ); 3177 | | 3178 | | if ( 3179 | | usageFactor > optimalUsageFactor && 3180 | | Precision.FLOAT_PRECISION > optimalUsageFactor 3181 | | ) { 3182 | | uint256 diff = usageFactor - optimalUsageFactor; 3183 | | 3184 | | uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint( 3185 | | Keys.aboveOptimalUsageBorrowingFactorKey( 3186 | | market.marketToken, 3187 | | isLong 3188 | | ) 3189 | | ); 3190 | | uint256 additionalBorrowingFactorPerSecond; 3191 | | 3192 | | if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) { 3193 | | additionalBorrowingFactorPerSecond = 3194 | | aboveOptimalUsageBorrowingFactor - 3195 | | baseBorrowingFactor; 3196 | | } 3197 | | 3198 | | uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor; 3199 | | 3200 | | borrowingFactorPerSecond += 3201 | | (additionalBorrowingFactorPerSecond * diff) / 3202 | | divisor; 3203 | | } 3204 | | 3205 | | return borrowingFactorPerSecond; 3206 | | } 3207 | | 3208 | * | function distributePositionImpactPool( 3209 | | DataStore dataStore, 3210 | | EventEmitter eventEmitter, 3211 | | address market 3212 | * | ) internal { 3213 | * | ( 3214 | * | uint256 distributionAmount, 3215 | * | uint256 nextPositionImpactPoolAmount 3216 | * | ) = getPendingPositionImpactPoolDistributionAmount(dataStore, market); 3217 | | 3218 | * | if (distributionAmount != 0) { 3219 | | applyDeltaToPositionImpactPool( 3220 | | dataStore, 3221 | | eventEmitter, 3222 | | market, 3223 | | -distributionAmount.toInt256() 3224 | | ); 3225 | | 3226 | | MarketEventUtils.emitPositionImpactPoolDistributed( 3227 | | eventEmitter, 3228 | | market, 3229 | | distributionAmount, 3230 | | nextPositionImpactPoolAmount 3231 | | ); 3232 | | } 3233 | | 3234 | * | dataStore.setUint( 3235 | * | Keys.positionImpactPoolDistributedAtKey(market), 3236 | * | Chain.currentTimestamp() 3237 | | ); 3238 | | } 3239 | | 3240 | * | function getNextPositionImpactPoolAmount( 3241 | | DataStore dataStore, 3242 | | address market 3243 | * | ) internal view returns (uint256) { 3244 | * | ( 3245 | | , 3246 | * | /* uint256 distributionAmount */ uint256 nextPositionImpactPoolAmount 3247 | * | ) = getPendingPositionImpactPoolDistributionAmount(dataStore, market); 3248 | | 3249 | * | return nextPositionImpactPoolAmount; 3250 | | } 3251 | | 3252 | | // @return (distributionAmount, nextPositionImpactPoolAmount) 3253 | * | function getPendingPositionImpactPoolDistributionAmount( 3254 | | DataStore dataStore, 3255 | | address market 3256 | * | ) internal view returns (uint256, uint256) { 3257 | * | uint256 positionImpactPoolAmount = getPositionImpactPoolAmount( 3258 | * | dataStore, 3259 | * | market 3260 | | ); 3261 | * | if (positionImpactPoolAmount == 0) { 3262 | * | return (0, positionImpactPoolAmount); 3263 | | } 3264 | | 3265 | * | uint256 distributionRate = dataStore.getUint( 3266 | * | Keys.positionImpactPoolDistributionRateKey(market) 3267 | | ); 3268 | * | if (distributionRate == 0) { 3269 | * | return (0, positionImpactPoolAmount); 3270 | | } 3271 | | 3272 | | uint256 minPositionImpactPoolAmount = dataStore.getUint( 3273 | | Keys.minPositionImpactPoolAmountKey(market) 3274 | | ); 3275 | | if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { 3276 | | return (0, positionImpactPoolAmount); 3277 | | } 3278 | | 3279 | | uint256 maxDistributionAmount = positionImpactPoolAmount - 3280 | | minPositionImpactPoolAmount; 3281 | | 3282 | | uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed( 3283 | | dataStore, 3284 | | market 3285 | | ); 3286 | | uint256 distributionAmount = Precision.applyFactor( 3287 | | durationInSeconds, 3288 | | distributionRate 3289 | | ); 3290 | | 3291 | | if (distributionAmount > maxDistributionAmount) { 3292 | | distributionAmount = maxDistributionAmount; 3293 | | } 3294 | | 3295 | | return ( 3296 | | distributionAmount, 3297 | | positionImpactPoolAmount - distributionAmount 3298 | | ); 3299 | | } 3300 | | 3301 | | function getSecondsSincePositionImpactPoolDistributed( 3302 | | DataStore dataStore, 3303 | | address market 3304 | | ) internal view returns (uint256) { 3305 | | uint256 distributedAt = dataStore.getUint( 3306 | | Keys.positionImpactPoolDistributedAtKey(market) 3307 | | ); 3308 | | if (distributedAt == 0) { 3309 | | return 0; 3310 | | } 3311 | | return Chain.currentTimestamp() - distributedAt; 3312 | | } 3313 | | 3314 | | // @dev get the total pending borrowing fees 3315 | | // @param dataStore DataStore 3316 | | // @param market the market to check 3317 | | // @param longToken the long token of the market 3318 | | // @param shortToken the short token of the market 3319 | | // @param isLong whether to check the long or short side 3320 | * | function getTotalPendingBorrowingFees( 3321 | | DataStore dataStore, 3322 | | Market.Props memory market, 3323 | | MarketPrices memory prices, 3324 | | bool isLong 3325 | * | ) internal view returns (uint256) { 3326 | * | uint256 openInterest = getOpenInterest(dataStore, market, isLong); 3327 | | 3328 | * | ( 3329 | * | uint256 nextCumulativeBorrowingFactor /* uint256 delta */, 3330 | | 3331 | * | ) = getNextCumulativeBorrowingFactor(dataStore, market, prices, isLong); 3332 | | 3333 | * | uint256 totalBorrowing = getTotalBorrowing( 3334 | * | dataStore, 3335 | * | market.marketToken, 3336 | * | isLong 3337 | | ); 3338 | | 3339 | * | return 3340 | * | Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - 3341 | * | totalBorrowing; 3342 | | } 3343 | | 3344 | | // @dev get the total borrowing value 3345 | | // the total borrowing value is the sum of position.borrowingFactor * position.size / (10 ^ 30) 3346 | | // for all positions of the market 3347 | | // if borrowing APR is 1000% for 100 years, the cumulativeBorrowingFactor could be as high as 100 * 1000 * (10 ** 30) 3348 | | // since position.size is a USD value with 30 decimals, under this scenario, there may be overflow issues 3349 | | // if open interest exceeds (2 ** 256) / (10 ** 30) / (100 * 1000 * (10 ** 30)) => 1,157,920,900,000 USD 3350 | | // @param dataStore DataStore 3351 | | // @param market the market to check 3352 | | // @param isLong whether to check the long or short side 3353 | | // @return the total borrowing value 3354 | * | function getTotalBorrowing( 3355 | | DataStore dataStore, 3356 | | address market, 3357 | | bool isLong 3358 | * | ) internal view returns (uint256) { 3359 | * | return dataStore.getUint(Keys.totalBorrowingKey(market, isLong)); 3360 | | } 3361 | | 3362 | | // @dev set the total borrowing value 3363 | | // @param dataStore DataStore 3364 | | // @param market the market to set 3365 | | // @param isLong whether to set the long or short side 3366 | | // @param value the value to set to 3367 | * | function setTotalBorrowing( 3368 | | DataStore dataStore, 3369 | | address market, 3370 | | bool isLong, 3371 | | uint256 value 3372 | * | ) internal returns (uint256) { 3373 | * | return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value); 3374 | | } 3375 | | 3376 | | // @dev convert a USD value to number of market tokens 3377 | | // @param usdValue the input USD value 3378 | | // @param poolValue the value of the pool 3379 | | // @param supply the supply of market tokens 3380 | | // @return the number of market tokens 3381 | * | function usdToMarketTokenAmount( 3382 | | uint256 usdValue, 3383 | | uint256 poolValue, 3384 | | uint256 supply 3385 | * | ) internal pure returns (uint256) { 3386 | | // if the supply and poolValue is zero, use 1 USD as the token price 3387 | * | if (supply == 0 && poolValue == 0) { 3388 | | return Precision.floatToWei(usdValue); 3389 | | } 3390 | | 3391 | | // if the supply is zero and the poolValue is more than zero, 3392 | | // then include the poolValue for the amount of tokens minted so that 3393 | | // the market token price after mint would be 1 USD 3394 | * | if (supply == 0 && poolValue > 0) { 3395 | | return Precision.floatToWei(poolValue + usdValue); 3396 | | } 3397 | | 3398 | | // round market tokens down 3399 | * | return Precision.mulDiv(supply, usdValue, poolValue); 3400 | | } 3401 | | 3402 | | // @dev convert a number of market tokens to its USD value 3403 | | // @param marketTokenAmount the input number of market tokens 3404 | | // @param poolValue the value of the pool 3405 | | // @param supply the supply of market tokens 3406 | | // @return the USD value of the market tokens 3407 | * | function marketTokenAmountToUsd( 3408 | | uint256 marketTokenAmount, 3409 | | uint256 poolValue, 3410 | | uint256 supply 3411 | * | ) internal pure returns (uint256) { 3412 | * | if (supply == 0) { 3413 | | revert Errors.EmptyMarketTokenSupply(); 3414 | | } 3415 | | 3416 | * | return Precision.mulDiv(poolValue, marketTokenAmount, supply); 3417 | | } 3418 | | 3419 | | // @dev validate that the specified market exists and is enabled 3420 | | // @param dataStore DataStore 3421 | | // @param marketAddress the address of the market 3422 | * | function validateEnabledMarket( 3423 | | DataStore dataStore, 3424 | | address marketAddress 3425 | * | ) internal view { 3426 | * | Market.Props memory market = MarketStoreUtils.get( 3427 | * | dataStore, 3428 | * | marketAddress 3429 | | ); 3430 | * | validateEnabledMarket(dataStore, market); 3431 | | } 3432 | | 3433 | | // @dev validate that the specified market exists and is enabled 3434 | | // @param dataStore DataStore 3435 | | // @param market the market to check 3436 | * | function validateEnabledMarket( 3437 | | DataStore dataStore, 3438 | | Market.Props memory market 3439 | * | ) internal view { 3440 | * | if (market.marketToken == address(0)) { 3441 | | revert Errors.EmptyMarket(); 3442 | | } 3443 | | 3444 | * | bool isMarketDisabled = dataStore.getBool( 3445 | * | Keys.isMarketDisabledKey(market.marketToken) 3446 | | ); 3447 | * | if (isMarketDisabled) { 3448 | | revert Errors.DisabledMarket(market.marketToken); 3449 | | } 3450 | | } 3451 | | 3452 | | // @dev validate that the positions can be opened in the given market 3453 | | // @param market the market to check 3454 | * | function validatePositionMarket( 3455 | | DataStore dataStore, 3456 | | Market.Props memory market 3457 | | ) internal view { 3458 | * | validateEnabledMarket(dataStore, market); 3459 | | 3460 | * | if (isSwapOnlyMarket(market)) { 3461 | | revert Errors.InvalidPositionMarket(market.marketToken); 3462 | | } 3463 | | } 3464 | | 3465 | * | function validatePositionMarket( 3466 | | DataStore dataStore, 3467 | | address marketAddress 3468 | * | ) internal view { 3469 | * | Market.Props memory market = MarketStoreUtils.get( 3470 | * | dataStore, 3471 | * | marketAddress 3472 | | ); 3473 | * | validatePositionMarket(dataStore, market); 3474 | | } 3475 | | 3476 | | // @dev check if a market only supports swaps and not positions 3477 | | // @param market the market to check 3478 | * | function isSwapOnlyMarket( 3479 | | Market.Props memory market 3480 | * | ) internal pure returns (bool) { 3481 | * | return market.indexToken == address(0); 3482 | | } 3483 | | 3484 | | // @dev check if the given token is a collateral token of the market 3485 | | // @param market the market to check 3486 | | // @param token the token to check 3487 | * | function isMarketCollateralToken( 3488 | | Market.Props memory market, 3489 | | address token 3490 | * | ) internal pure returns (bool) { 3491 | * | return token == market.longToken || token == market.shortToken; 3492 | | } 3493 | | 3494 | | // @dev validate if the given token is a collateral token of the market 3495 | | // @param market the market to check 3496 | | // @param token the token to check 3497 | * | function validateMarketCollateralToken( 3498 | | Market.Props memory market, 3499 | | address token 3500 | | ) internal pure { 3501 | * | if (!isMarketCollateralToken(market, token)) { 3502 | | revert Errors.InvalidCollateralTokenForMarket( 3503 | | market.marketToken, 3504 | | token 3505 | | ); 3506 | | } 3507 | | } 3508 | | 3509 | | // @dev get the enabled market, revert if the market does not exist or is not enabled 3510 | | // @param dataStore DataStore 3511 | | // @param marketAddress the address of the market 3512 | * | function getEnabledMarket( 3513 | | DataStore dataStore, 3514 | | address marketAddress 3515 | * | ) internal view returns (Market.Props memory) { 3516 | * | Market.Props memory market = MarketStoreUtils.get( 3517 | * | dataStore, 3518 | * | marketAddress 3519 | | ); 3520 | * | validateEnabledMarket(dataStore, market); 3521 | * | return market; 3522 | | } 3523 | | 3524 | * | function getSwapPathMarket( 3525 | | DataStore dataStore, 3526 | | address marketAddress 3527 | * | ) internal view returns (Market.Props memory) { 3528 | * | Market.Props memory market = MarketStoreUtils.get( 3529 | * | dataStore, 3530 | * | marketAddress 3531 | | ); 3532 | * | validateSwapMarket(dataStore, market); 3533 | * | return market; 3534 | | } 3535 | | 3536 | | // @dev get a list of market values based on an input array of market addresses 3537 | | // @param swapPath list of market addresses 3538 | * | function getSwapPathMarkets( 3539 | | DataStore dataStore, 3540 | | address[] memory swapPath 3541 | * | ) internal view returns (Market.Props[] memory) { 3542 | * | Market.Props[] memory markets = new Market.Props[](swapPath.length); 3543 | | 3544 | * | for (uint256 i; i < swapPath.length; i++) { 3545 | * | address marketAddress = swapPath[i]; 3546 | * | markets[i] = getSwapPathMarket(dataStore, marketAddress); 3547 | | } 3548 | | 3549 | * | return markets; 3550 | | } 3551 | | 3552 | * | function validateSwapPath( 3553 | | DataStore dataStore, 3554 | | address[] memory swapPath 3555 | * | ) internal view { 3556 | * | uint256 maxSwapPathLength = dataStore.getUint( 3557 | | Keys.MAX_SWAP_PATH_LENGTH 3558 | | ); 3559 | * | if (swapPath.length > maxSwapPathLength) { 3560 | | revert Errors.MaxSwapPathLengthExceeded( 3561 | | swapPath.length, 3562 | | maxSwapPathLength 3563 | | ); 3564 | | } 3565 | | 3566 | * | for (uint256 i; i < swapPath.length; i++) { 3567 | * | address marketAddress = swapPath[i]; 3568 | * | validateSwapMarket(dataStore, marketAddress); 3569 | | } 3570 | | } 3571 | | 3572 | | // @dev validate that the pending pnl is below the allowed amount 3573 | | // @param dataStore DataStore 3574 | | // @param market the market to check 3575 | | // @param prices the prices of the market tokens 3576 | | // @param pnlFactorType the pnl factor type to check 3577 | | // function validateMaxPnl( 3578 | | // DataStore dataStore, 3579 | | // Market.Props memory market, 3580 | | // MarketPrices memory prices, 3581 | | // bytes32 pnlFactorTypeForLongs, 3582 | | // bytes32 pnlFactorTypeForShorts 3583 | | // ) internal view { 3584 | | // (bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded( 3585 | | // dataStore, 3586 | | // market, 3587 | | // prices, 3588 | | // true, 3589 | | // pnlFactorTypeForLongs 3590 | | // ); 3591 | | 3592 | | // if (isPnlFactorExceededForLongs) { 3593 | | // revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs); 3594 | | // } 3595 | | 3596 | | // (bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded( 3597 | | // dataStore, 3598 | | // market, 3599 | | // prices, 3600 | | // false, 3601 | | // pnlFactorTypeForShorts 3602 | | // ); 3603 | | 3604 | | // if (isPnlFactorExceededForShorts) { 3605 | | // revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts); 3606 | | // } 3607 | | // } 3608 | | 3609 | * | function validateMaxPnl( 3610 | | DataStore dataStore, 3611 | | Market.Props memory market, 3612 | | MarketPrices memory prices, 3613 | | bytes32 pnlFactorTypeForLongs, 3614 | | bytes32 pnlFactorTypeForShorts 3615 | * | ) internal view { 3616 | * | ( 3617 | * | bool isPnlFactorExceededForLongs, 3618 | * | int256 pnlToPoolFactorForLongs, 3619 | * | uint256 maxPnlFactorForLongs 3620 | * | ) = isPnlFactorExceeded( 3621 | * | dataStore, 3622 | * | market, 3623 | * | prices, 3624 | * | true, 3625 | * | pnlFactorTypeForLongs 3626 | | ); 3627 | | 3628 | | 3629 | * | if (isPnlFactorExceededForLongs) { 3630 | * | revert Errors.PnlFactorExceededForLongs( 3631 | * | pnlToPoolFactorForLongs, 3632 | * | maxPnlFactorForLongs 3633 | | ); 3634 | | } 3635 | | 3636 | * | ( 3637 | * | bool isPnlFactorExceededForShorts, 3638 | * | int256 pnlToPoolFactorForShorts, 3639 | * | uint256 maxPnlFactorForShorts 3640 | * | ) = isPnlFactorExceeded( 3641 | * | dataStore, 3642 | * | market, 3643 | * | prices, 3644 | * | false, 3645 | * | pnlFactorTypeForShorts 3646 | | ); 3647 | | 3648 | | 3649 | * | if (isPnlFactorExceededForShorts) { 3650 | | revert Errors.PnlFactorExceededForShorts( 3651 | | pnlToPoolFactorForShorts, 3652 | | maxPnlFactorForShorts 3653 | | ); 3654 | | } 3655 | | } 3656 | | 3657 | | // @dev check if the pending pnl exceeds the allowed amount 3658 | | // @param dataStore DataStore 3659 | | // @param oracle Oracle 3660 | | // @param market the market to check 3661 | | // @param isLong whether to check the long or short side 3662 | | // @param pnlFactorType the pnl factor type to check 3663 | * | function isPnlFactorExceeded( 3664 | | DataStore dataStore, 3665 | | Oracle oracle, 3666 | | address market, 3667 | | bool isLong, 3668 | | bytes32 pnlFactorType 3669 | * | ) internal view returns (bool, int256, uint256) { 3670 | * | Market.Props memory _market = getEnabledMarket(dataStore, market); 3671 | * | MarketPrices memory prices = getMarketPrices(oracle, _market); 3672 | | 3673 | * | return 3674 | * | isPnlFactorExceeded( 3675 | * | dataStore, 3676 | * | _market, 3677 | * | prices, 3678 | * | isLong, 3679 | * | pnlFactorType 3680 | | ); 3681 | | } 3682 | | 3683 | | // @dev check if the pending pnl exceeds the allowed amount 3684 | | // @param dataStore DataStore 3685 | | // @param _market the market to check 3686 | | // @param prices the prices of the market tokens 3687 | | // @param isLong whether to check the long or short side 3688 | | // @param pnlFactorType the pnl factor type to check 3689 | | // function isPnlFactorExceeded( 3690 | | // DataStore dataStore, 3691 | | // Market.Props memory market, 3692 | | // MarketPrices memory prices, 3693 | | // bool isLong, 3694 | | // bytes32 pnlFactorType 3695 | | // ) internal view returns (bool, int256, uint256) { 3696 | | // int256 pnlToPoolFactor = getPnlToPoolFactor( 3697 | | // dataStore, 3698 | | // market, 3699 | | // prices, 3700 | | // isLong, 3701 | | // true 3702 | | // ); 3703 | | // uint256 maxPnlFactor = getMaxPnlFactor( 3704 | | // dataStore, 3705 | | // pnlFactorType, 3706 | | // market.marketToken, 3707 | | // isLong 3708 | | // ); 3709 | | 3710 | | // bool isExceeded = pnlToPoolFactor > 0 && 3711 | | // pnlToPoolFactor.toUint256() > maxPnlFactor; 3712 | | 3713 | | // return (isExceeded, pnlToPoolFactor, maxPnlFactor); 3714 | | // } 3715 | | 3716 | * | function isPnlFactorExceeded( 3717 | | DataStore dataStore, 3718 | | Market.Props memory market, 3719 | | MarketPrices memory prices, 3720 | | bool isLong, 3721 | | bytes32 pnlFactorType 3722 | * | ) internal view returns (bool, int256, uint256) { 3723 | | 3724 | * | int256 pnlToPoolFactor = getPnlToPoolFactor( 3725 | * | dataStore, 3726 | * | market, 3727 | * | prices, 3728 | * | isLong, 3729 | * | true 3730 | | ); 3731 | | 3732 | * | uint256 maxPnlFactor = getMaxPnlFactor( 3733 | * | dataStore, 3734 | * | pnlFactorType, 3735 | * | market.marketToken, 3736 | * | isLong 3737 | | ); 3738 | | 3739 | * | bool isExceeded = pnlToPoolFactor > 0 && 3740 | * | pnlToPoolFactor.toUint256() > maxPnlFactor; 3741 | | 3742 | * | return (isExceeded, pnlToPoolFactor, maxPnlFactor); 3743 | | } 3744 | | 3745 | * | function getUiFeeFactor( 3746 | | DataStore dataStore, 3747 | | address account 3748 | * | ) internal view returns (uint256) { 3749 | * | uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR); 3750 | * | uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account)); 3751 | | 3752 | * | return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor; 3753 | | } 3754 | | 3755 | | function setUiFeeFactor( 3756 | | DataStore dataStore, 3757 | | EventEmitter eventEmitter, 3758 | | address account, 3759 | | uint256 uiFeeFactor 3760 | | ) internal { 3761 | | uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR); 3762 | | 3763 | | if (uiFeeFactor > maxUiFeeFactor) { 3764 | | revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor); 3765 | | } 3766 | | 3767 | | dataStore.setUint(Keys.uiFeeFactorKey(account), uiFeeFactor); 3768 | | 3769 | | MarketEventUtils.emitUiFeeFactorUpdated( 3770 | | eventEmitter, 3771 | | account, 3772 | | uiFeeFactor 3773 | | ); 3774 | | } 3775 | | 3776 | * | function validateMarketTokenBalance( 3777 | | DataStore dataStore, 3778 | | Market.Props[] memory markets 3779 | | ) internal view { 3780 | * | for (uint256 i; i < markets.length; i++) { 3781 | * | validateMarketTokenBalance(dataStore, markets[i]); 3782 | | } 3783 | | } 3784 | | 3785 | * | function validateMarketTokenBalance( 3786 | | DataStore dataStore, 3787 | | address _market 3788 | * | ) internal view { 3789 | * | Market.Props memory market = getEnabledMarket(dataStore, _market); 3790 | * | validateMarketTokenBalance(dataStore, market); 3791 | | } 3792 | | 3793 | * | function validateMarketTokenBalance( 3794 | | DataStore dataStore, 3795 | | Market.Props memory market 3796 | | ) internal view { 3797 | * | validateMarketTokenBalance(dataStore, market, market.longToken); 3798 | | 3799 | * | if (market.longToken == market.shortToken) { 3800 | * | return; 3801 | | } 3802 | | 3803 | * | validateMarketTokenBalance(dataStore, market, market.shortToken); 3804 | | } 3805 | | 3806 | * | function validateMarketTokenBalance( 3807 | | DataStore dataStore, 3808 | | Market.Props memory market, 3809 | | address token 3810 | * | ) internal view { 3811 | * | if (market.marketToken == address(0) || token == address(0)) { 3812 | | revert Errors.EmptyAddressInMarketTokenBalanceValidation( 3813 | | market.marketToken, 3814 | | token 3815 | | ); 3816 | | } 3817 | | 3818 | * | uint256 balance = IERC20(token).balanceOf(market.marketToken); 3819 | * | uint256 expectedMinBalance = getExpectedMinTokenBalance( 3820 | * | dataStore, 3821 | * | market, 3822 | * | token 3823 | | ); 3824 | | 3825 | * | if (balance < expectedMinBalance) { 3826 | * | revert Errors.InvalidMarketTokenBalance( 3827 | * | market.marketToken, 3828 | * | token, 3829 | * | balance, 3830 | * | expectedMinBalance 3831 | | ); 3832 | | } 3833 | | 3834 | | // funding fees can be claimed even if the collateral for positions that should pay funding fees 3835 | | // hasn't been reduced yet 3836 | | // due to that, funding fees and collateral is excluded from the expectedMinBalance calculation 3837 | | // and validated separately 3838 | | 3839 | | // use 1 for the getCollateralSum divisor since getCollateralSum does not sum over both the 3840 | | // longToken and shortToken 3841 | * | uint256 collateralAmount = getCollateralSum( 3842 | * | dataStore, 3843 | * | market.marketToken, 3844 | * | token, 3845 | * | true, 3846 | * | 1 3847 | | ); 3848 | * | collateralAmount += getCollateralSum( 3849 | * | dataStore, 3850 | * | market.marketToken, 3851 | * | token, 3852 | * | false, 3853 | * | 1 3854 | | ); 3855 | | 3856 | * | if (balance < collateralAmount) { 3857 | | revert Errors.InvalidMarketTokenBalanceForCollateralAmount( 3858 | | market.marketToken, 3859 | | token, 3860 | | balance, 3861 | | collateralAmount 3862 | | ); 3863 | | } 3864 | | 3865 | * | uint256 claimableFundingFeeAmount = dataStore.getUint( 3866 | * | Keys.claimableFundingAmountKey(market.marketToken, token) 3867 | | ); 3868 | | 3869 | | // in case of late liquidations, it may be possible for the claimableFundingFeeAmount to exceed the market token balance 3870 | | // but this should be very rare 3871 | * | if (balance < claimableFundingFeeAmount) { 3872 | | revert Errors.InvalidMarketTokenBalanceForClaimableFunding( 3873 | | market.marketToken, 3874 | | token, 3875 | | balance, 3876 | | claimableFundingFeeAmount 3877 | | ); 3878 | | } 3879 | | } 3880 | | 3881 | * | function getExpectedMinTokenBalance( 3882 | | DataStore dataStore, 3883 | | Market.Props memory market, 3884 | | address token 3885 | * | ) internal view returns (uint256) { 3886 | * | GetExpectedMinTokenBalanceCache memory cache; 3887 | | 3888 | | // get the pool amount directly as MarketUtils.getPoolAmount will divide the amount by 2 3889 | | // for markets with the same long and short token 3890 | * | cache.poolAmount = dataStore.getUint( 3891 | * | Keys.poolAmountKey(market.marketToken, token) 3892 | | ); 3893 | * | cache.swapImpactPoolAmount = getSwapImpactPoolAmount( 3894 | * | dataStore, 3895 | * | market.marketToken, 3896 | * | token 3897 | | ); 3898 | * | cache.claimableCollateralAmount = dataStore.getUint( 3899 | * | Keys.claimableCollateralAmountKey(market.marketToken, token) 3900 | | ); 3901 | * | cache.claimableFeeAmount = dataStore.getUint( 3902 | * | Keys.claimableFeeAmountKey(market.marketToken, token) 3903 | | ); 3904 | * | cache.claimableUiFeeAmount = dataStore.getUint( 3905 | * | Keys.claimableUiFeeAmountKey(market.marketToken, token) 3906 | | ); 3907 | * | cache.affiliateRewardAmount = dataStore.getUint( 3908 | * | Keys.affiliateRewardKey(market.marketToken, token) 3909 | | ); 3910 | | 3911 | | // funding fees are excluded from this summation as claimable funding fees 3912 | | // are incremented without a corresponding decrease of the collateral of 3913 | | // other positions, the collateral of other positions is decreased when 3914 | | // those positions are updated 3915 | * | return 3916 | * | cache.poolAmount + 3917 | * | cache.swapImpactPoolAmount + 3918 | * | cache.claimableCollateralAmount + 3919 | * | cache.claimableFeeAmount + 3920 | * | cache.claimableUiFeeAmount + 3921 | * | cache.affiliateRewardAmount; 3922 | | } 3923 | | } 3924 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/migration/TimestampInitializer.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../chain/Chain.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../event/EventEmitter.sol"; 8 | | import "../role/RoleModule.sol"; 9 | | import "../order/OrderStoreUtils.sol"; 10 | | import "../position/PositionStoreUtils.sol"; 11 | | 12 | | contract TimestampInitializer is RoleModule { 13 | | using EventUtils for EventUtils.AddressItems; 14 | | using EventUtils for EventUtils.UintItems; 15 | | using EventUtils for EventUtils.IntItems; 16 | | using EventUtils for EventUtils.BoolItems; 17 | | using EventUtils for EventUtils.Bytes32Items; 18 | | using EventUtils for EventUtils.BytesItems; 19 | | using EventUtils for EventUtils.StringItems; 20 | | 21 | | DataStore public immutable dataStore; 22 | | EventEmitter public immutable eventEmitter; 23 | | 24 | | constructor( 25 | | RoleStore _roleStore, 26 | | DataStore _dataStore, 27 | | EventEmitter _eventEmitter 28 | | ) RoleModule(_roleStore) { 29 | | dataStore = _dataStore; 30 | | eventEmitter = _eventEmitter; 31 | | } 32 | | 33 | | 34 | | function initializeOrderTimestamps(uint256 start, uint256 end) external onlyConfigKeeper { 35 | | bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end); 36 | | uint256 currentTimestamp = Chain.currentTimestamp(); 37 | | 38 | | for (uint256 i; i < keys.length; i++) { 39 | | bytes32 key = keys[i]; 40 | | 41 | | uint256 updatedAtTime = dataStore.getUint( 42 | | keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME)) 43 | | ); 44 | | 45 | | if (updatedAtTime == 0) { 46 | | 47 | | dataStore.setUint( 48 | | keccak256(abi.encode(key, OrderStoreUtils.UPDATED_AT_TIME)), 49 | | currentTimestamp 50 | | ); 51 | | 52 | | EventUtils.EventLogData memory eventData; 53 | | eventData.bytes32Items.initItems(1); 54 | | eventData.bytes32Items.setItem(0, "key", key); 55 | | 56 | | eventData.uintItems.initItems(1); 57 | | eventData.uintItems.setItem(0, "updatedAtTime", currentTimestamp); 58 | | 59 | | eventEmitter.emitEventLog( 60 | | "InitializeOrderUpdatedAtTime", 61 | | eventData 62 | | ); 63 | | } 64 | | } 65 | | } 66 | | 67 | | function initializePositionTimestamps(uint256 start, uint256 end) external onlyConfigKeeper { 68 | | bytes32[] memory keys = dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end); 69 | | uint256 currentTimestamp = Chain.currentTimestamp(); 70 | | 71 | | for (uint256 i; i < keys.length; i++) { 72 | | bytes32 key = keys[i]; 73 | | 74 | | uint256 increasedAtTime = dataStore.getUint( 75 | | keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME)) 76 | | ); 77 | | 78 | | if (increasedAtTime == 0) { 79 | | dataStore.setUint( 80 | | keccak256(abi.encode(key, PositionStoreUtils.INCREASED_AT_TIME)), 81 | | currentTimestamp 82 | | ); 83 | | 84 | | EventUtils.EventLogData memory eventData; 85 | | eventData.bytes32Items.initItems(1); 86 | | eventData.bytes32Items.setItem(0, "key", key); 87 | | 88 | | eventData.uintItems.initItems(1); 89 | | eventData.uintItems.setItem(0, "increasedAtTime", currentTimestamp); 90 | | 91 | | eventEmitter.emitEventLog( 92 | | "InitializePositionIncreasedAtTime", 93 | | eventData 94 | | ); 95 | | } 96 | | 97 | | uint256 decreasedAtTime = dataStore.getUint( 98 | | keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME)) 99 | | ); 100 | | 101 | | if (decreasedAtTime == 0) { 102 | | dataStore.setUint( 103 | | keccak256(abi.encode(key, PositionStoreUtils.DECREASED_AT_TIME)), 104 | | currentTimestamp 105 | | ); 106 | | 107 | | EventUtils.EventLogData memory eventData; 108 | | eventData.bytes32Items.initItems(1); 109 | | eventData.bytes32Items.setItem(0, "key", key); 110 | | 111 | | eventData.uintItems.initItems(1); 112 | | eventData.uintItems.setItem(0, "decreasedAtTime", currentTimestamp); 113 | | 114 | | eventEmitter.emitEventLog( 115 | | "InitializePositionDecreasedAtTime", 116 | | eventData 117 | | ); 118 | | } 119 | | } 120 | | } 121 | | 122 | | } 123 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/Governable.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../error/Errors.sol"; 6 | | 7 | | // @title Governable 8 | | // @dev Contract to allow for governance restricted functions 9 | | contract Governable { 10 | | address public gov; 11 | | address public pendingGov; 12 | | 13 | | event SetGov(address prevGov, address nextGov); 14 | | 15 | | constructor() { 16 | | _setGov(msg.sender); 17 | | } 18 | | 19 | | modifier onlyGov() { 20 | | if (msg.sender != gov) { 21 | | revert Errors.Unauthorized(msg.sender, "GOV"); 22 | | } 23 | | _; 24 | | } 25 | | 26 | | function transferOwnership(address _newGov) external onlyGov { 27 | | pendingGov = _newGov; 28 | | } 29 | | 30 | | function acceptOwnership() external { 31 | | if (msg.sender != pendingGov) { 32 | | revert Errors.Unauthorized(msg.sender, "PendingGov"); 33 | | } 34 | | 35 | | _setGov(msg.sender); 36 | | } 37 | | 38 | | // @dev updates the gov value to the input _gov value 39 | | // @param _gov the value to update to 40 | | function _setGov(address _gov) internal { 41 | | address prevGov = gov; 42 | | gov = _gov; 43 | | 44 | | emit SetGov(prevGov, _gov); 45 | | } 46 | | } 47 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MintableToken.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | | 7 | | // @title MintableToken 8 | | // @dev Mock mintable token for testing and testnets 9 | * | contract MintableToken is ERC20 { 10 | | uint8 private _decimals; 11 | | 12 | | constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { 13 | | _decimals = decimals_; 14 | | } 15 | | 16 | | function decimals() public view virtual override returns (uint8) { 17 | | return _decimals; 18 | | } 19 | | 20 | | // @dev mint tokens to an account 21 | | // @param account the account to mint to 22 | | // @param amount the amount of tokens to mint 23 | | function mint(address account, uint256 amount) external { 24 | | _mint(account, amount); 25 | | } 26 | | 27 | | // @dev burn tokens from an account 28 | | // @param account the account to burn tokens for 29 | | // @param amount the amount of tokens to burn 30 | | function burn(address account, uint256 amount) external { 31 | | _burn(account, amount); 32 | | } 33 | | } 34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MockDataStreamVerifier.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../oracle/IChainlinkDataStreamVerifier.sol"; 6 | | 7 | * | contract MockDataStreamVerifier is IChainlinkDataStreamVerifier { 8 | | function verify( 9 | | bytes calldata payload, 10 | | bytes calldata parameterPayload 11 | | ) external payable returns (bytes memory) { 12 | | (address feeToken) = abi.decode(parameterPayload, (address)); 13 | | require(feeToken == 0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf, "invalid fee token"); 14 | | 15 | | return payload; 16 | | } 17 | | } 18 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/MockPriceFeed.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../oracle/IPriceFeed.sol"; 6 | | 7 | | // @title MockPriceFeed 8 | | // @dev Mock price feed for testing and testnets 9 | * | contract MockPriceFeed is IPriceFeed { 10 | | int256 public answer; 11 | | 12 | | // @dev set answer 13 | | // @param _answer the answer to set to 14 | | function setAnswer(int256 _answer) external { 15 | | answer = _answer; 16 | | } 17 | | 18 | | function latestAnswer() external view returns (int256) { 19 | | return answer; 20 | | } 21 | | 22 | | // @dev get the latest data 23 | | // @return (roundId, answer, startedAt, updatedAt, answeredInRound) 24 | | function latestRoundData() external view returns ( 25 | | uint80, 26 | | int256, 27 | | uint256, 28 | | uint256, 29 | | uint80 30 | | ) { 31 | | return ( 32 | | uint80(0), // roundId 33 | | answer, // answer 34 | | 0, // startedAt 35 | | block.timestamp - 60, // updatedAt 36 | | uint80(0) // answeredInRound 37 | | ); 38 | | } 39 | | } 40 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/Multicall3.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | /// @title Multicall3 5 | | /// @notice Aggregate results from multiple function calls 6 | | /// @dev Multicall & Multicall2 backwards-compatible 7 | | /// @dev Aggregate methods are marked `payable` to save 24 gas per call 8 | | /// @author Michael Elliot <mike@makerdao.com> 9 | | /// @author Joshua Levine <joshua@makerdao.com> 10 | | /// @author Nick Johnson <arachnid@notdot.net> 11 | | /// @author Andreas Bigger <andreas@nascent.xyz> 12 | | /// @author Matt Solomon <matt@mattsolomon.dev> 13 | * | contract Multicall3 { 14 | | struct Call { 15 | | address target; 16 | | bytes callData; 17 | | } 18 | | 19 | | struct Call3 { 20 | | address target; 21 | | bool allowFailure; 22 | | bytes callData; 23 | | } 24 | | 25 | | struct Call3Value { 26 | | address target; 27 | | bool allowFailure; 28 | | uint256 value; 29 | | bytes callData; 30 | | } 31 | | 32 | | struct Result { 33 | | bool success; 34 | | bytes returnData; 35 | | } 36 | | 37 | | /// @notice Backwards-compatible call aggregation with Multicall 38 | | /// @param calls An array of Call structs 39 | | /// @return blockNumber The block number where the calls were executed 40 | | /// @return returnData An array of bytes containing the responses 41 | | function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { 42 | | blockNumber = block.number; 43 | | uint256 length = calls.length; 44 | | returnData = new bytes[](length); 45 | | Call calldata call; 46 | | for (uint256 i; i < length;) { 47 | | bool success; 48 | | call = calls[i]; 49 | | (success, returnData[i]) = call.target.call(call.callData); 50 | | require(success, "Multicall3: call failed"); 51 | | unchecked { ++i; } 52 | | } 53 | | } 54 | | 55 | | /// @notice Backwards-compatible with Multicall2 56 | | /// @notice Aggregate calls without requiring success 57 | | /// @param requireSuccess If true, require all calls to succeed 58 | | /// @param calls An array of Call structs 59 | | /// @return returnData An array of Result structs 60 | | function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) { 61 | | uint256 length = calls.length; 62 | | returnData = new Result[](length); 63 | | Call calldata call; 64 | | for (uint256 i; i < length;) { 65 | | Result memory result = returnData[i]; 66 | | call = calls[i]; 67 | | (result.success, result.returnData) = call.target.call(call.callData); 68 | | if (requireSuccess) require(result.success, "Multicall3: call failed"); 69 | | unchecked { ++i; } 70 | | } 71 | | } 72 | | 73 | | /// @notice Backwards-compatible with Multicall2 74 | | /// @notice Aggregate calls and allow failures using tryAggregate 75 | | /// @param calls An array of Call structs 76 | | /// @return blockNumber The block number where the calls were executed 77 | | /// @return blockHash The hash of the block where the calls were executed 78 | | /// @return returnData An array of Result structs 79 | | function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { 80 | | blockNumber = block.number; 81 | | blockHash = blockhash(block.number); 82 | | returnData = tryAggregate(requireSuccess, calls); 83 | | } 84 | | 85 | | /// @notice Backwards-compatible with Multicall2 86 | | /// @notice Aggregate calls and allow failures using tryAggregate 87 | | /// @param calls An array of Call structs 88 | | /// @return blockNumber The block number where the calls were executed 89 | | /// @return blockHash The hash of the block where the calls were executed 90 | | /// @return returnData An array of Result structs 91 | | function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { 92 | | (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); 93 | | } 94 | | 95 | | /// @notice Aggregate calls, ensuring each returns success if required 96 | | /// @param calls An array of Call3 structs 97 | | /// @return returnData An array of Result structs 98 | | function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { 99 | | uint256 length = calls.length; 100 | | returnData = new Result[](length); 101 | | Call3 calldata calli; 102 | | for (uint256 i; i < length;) { 103 | | Result memory result = returnData[i]; 104 | | calli = calls[i]; 105 | | (result.success, result.returnData) = calli.target.call(calli.callData); 106 | | assembly { 107 | | // Revert if the call fails and failure is not allowed 108 | | // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` 109 | | if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { 110 | | // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) 111 | | mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) 112 | | // set data offset 113 | | mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) 114 | | // set length of revert string 115 | | mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) 116 | | // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) 117 | | mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) 118 | | revert(0x00, 0x64) 119 | | } 120 | | } 121 | | unchecked { ++i; } 122 | | } 123 | | } 124 | | 125 | | /// @notice Aggregate calls with a msg value 126 | | /// @notice Reverts if msg.value is less than the sum of the call values 127 | | /// @param calls An array of Call3Value structs 128 | | /// @return returnData An array of Result structs 129 | | function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { 130 | | uint256 valAccumulator; 131 | | uint256 length = calls.length; 132 | | returnData = new Result[](length); 133 | | Call3Value calldata calli; 134 | | for (uint256 i; i < length;) { 135 | | Result memory result = returnData[i]; 136 | | calli = calls[i]; 137 | | uint256 val = calli.value; 138 | | // Humanity will be a Type V Kardashev Civilization before this overflows - andreas 139 | | // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 140 | | unchecked { valAccumulator += val; } 141 | | (result.success, result.returnData) = calli.target.call{value: val}(calli.callData); 142 | | assembly { 143 | | // Revert if the call fails and failure is not allowed 144 | | // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` 145 | | if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { 146 | | // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) 147 | | mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) 148 | | // set data offset 149 | | mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) 150 | | // set length of revert string 151 | | mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) 152 | | // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) 153 | | mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) 154 | | revert(0x00, 0x84) 155 | | } 156 | | } 157 | | unchecked { ++i; } 158 | | } 159 | | // Finally, make sure the msg.value = SUM(call[0...i].value) 160 | | require(msg.value == valAccumulator, "Multicall3: value mismatch"); 161 | | } 162 | | 163 | | /// @notice Returns the block hash for the given block number 164 | | /// @param blockNumber The block number 165 | | function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { 166 | | blockHash = blockhash(blockNumber); 167 | | } 168 | | 169 | | /// @notice Returns the block number 170 | | function getBlockNumber() public view returns (uint256 blockNumber) { 171 | | blockNumber = block.number; 172 | | } 173 | | 174 | | /// @notice Returns the block coinbase 175 | | function getCurrentBlockCoinbase() public view returns (address coinbase) { 176 | | coinbase = block.coinbase; 177 | | } 178 | | 179 | | /// @notice Returns the block gas limit 180 | | function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { 181 | | gaslimit = block.gaslimit; 182 | | } 183 | | 184 | | /// @notice Returns the block timestamp 185 | | function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { 186 | | timestamp = block.timestamp; 187 | | } 188 | | 189 | | /// @notice Returns the (ETH) balance of a given address 190 | | function getEthBalance(address addr) public view returns (uint256 balance) { 191 | | balance = addr.balance; 192 | | } 193 | | 194 | | /// @notice Returns the block hash of the last block 195 | | function getLastBlockHash() public view returns (bytes32 blockHash) { 196 | | unchecked { 197 | | blockHash = blockhash(block.number - 1); 198 | | } 199 | | } 200 | | 201 | | /// @notice Gets the base fee of the given block 202 | | /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain 203 | | function getBasefee() public view returns (uint256 basefee) { 204 | | basefee = block.basefee; 205 | | } 206 | | 207 | | /// @notice Returns the chain id 208 | | function getChainId() public view returns (uint256 chainid) { 209 | | chainid = block.chainid; 210 | | } 211 | | } 212 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/ReferralStorage.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../referral/IReferralStorage.sol"; 6 | | import "./Governable.sol"; 7 | | 8 | | // @title ReferralStorage 9 | | // @dev Mock referral storage for testing and testnets 10 | * | contract ReferralStorage is IReferralStorage, Governable { 11 | | uint256 public constant BASIS_POINTS = 10000; 12 | | 13 | | // @dev mapping of affiliate to discount share for trader 14 | | // this overrides the default value in the affiliate's tier 15 | | mapping (address => uint256) public override referrerDiscountShares; 16 | | // @dev mapping of affiliate to tier 17 | | mapping (address => uint256) public override referrerTiers; 18 | | // @dev mapping tier level to tier values 19 | | mapping (uint256 => ReferralTier.Props) public override tiers; 20 | | 21 | | // @dev handlers for access control 22 | | mapping (address => bool) public isHandler; 23 | | 24 | | // @dev mapping of referral code to affiliate 25 | | mapping (bytes32 => address) public override codeOwners; 26 | | // @dev mapping of trader to referral code 27 | * | mapping (address => bytes32) public override traderReferralCodes; 28 | | 29 | | // @param handler the handler being set 30 | | // @param isActive whether the handler is being set to active or inactive 31 | | event SetHandler(address handler, bool isActive); 32 | | // @param account address of the trader 33 | | // @param code the referral code 34 | | event SetTraderReferralCode(address account, bytes32 code); 35 | | // @param tierId the tier level 36 | | // @param totalRebate the total rebate for the tier (affiliate reward + trader discount) 37 | | // @param discountShare the share of the totalRebate for traders 38 | | event SetTier(uint256 tierId, uint256 totalRebate, uint256 discountShare); 39 | | // @param referrer the affiliate 40 | | // @param tierId the new tier level 41 | | event SetReferrerTier(address referrer, uint256 tierId); 42 | | // @param referrer the affiliate 43 | | // @param discountShare the share of the totalRebate for traders 44 | | event SetReferrerDiscountShare(address referrer, uint256 discountShare); 45 | | // @param account the address of the affiliate 46 | | // @param code the referral code 47 | | event RegisterCode(address account, bytes32 code); 48 | | // @param account the previous owner of the referral code 49 | | // @param newAccount the new owner of the referral code 50 | | // @param code the referral code 51 | | event SetCodeOwner(address account, address newAccount, bytes32 code); 52 | | // @param newAccount the new owner of the referral code 53 | | // @param code the referral code 54 | | event GovSetCodeOwner(bytes32 code, address newAccount); 55 | | 56 | | modifier onlyHandler() { 57 | | require(isHandler[msg.sender], "ReferralStorage: forbidden"); 58 | | _; 59 | | } 60 | | 61 | | // @dev set an address as a handler 62 | | // @param _handler address of the handler 63 | | // @param _isActive whether to set the handler as active or inactive 64 | | function setHandler(address _handler, bool _isActive) external onlyGov { 65 | | isHandler[_handler] = _isActive; 66 | | emit SetHandler(_handler, _isActive); 67 | | } 68 | | 69 | | // @dev set values for a tier 70 | | // @param _tierId the ID of the tier to set 71 | | // @param _totalRebate the total rebate 72 | | // @param _discountShare the discount share 73 | | function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external override onlyGov { 74 | | require(_totalRebate <= BASIS_POINTS, "ReferralStorage: invalid totalRebate"); 75 | | require(_discountShare <= BASIS_POINTS, "ReferralStorage: invalid discountShare"); 76 | | 77 | | ReferralTier.Props memory tier = tiers[_tierId]; 78 | | tier.totalRebate = _totalRebate; 79 | | tier.discountShare = _discountShare; 80 | | tiers[_tierId] = tier; 81 | | emit SetTier(_tierId, _totalRebate, _discountShare); 82 | | } 83 | | 84 | | // @dev set the tier for an affiliate 85 | | // @param _referrer the address of the affiliate 86 | | // @param _tierId the tier to set to 87 | | function setReferrerTier(address _referrer, uint256 _tierId) external override onlyGov { 88 | | referrerTiers[_referrer] = _tierId; 89 | | emit SetReferrerTier(_referrer, _tierId); 90 | | } 91 | | 92 | | // @dev set the discount share for an affiliate 93 | | // @param _discountShare the discount share to set to 94 | | function setReferrerDiscountShare(uint256 _discountShare) external { 95 | | require(_discountShare <= BASIS_POINTS, "ReferralStorage: invalid discountShare"); 96 | | 97 | | referrerDiscountShares[msg.sender] = _discountShare; 98 | | emit SetReferrerDiscountShare(msg.sender, _discountShare); 99 | | } 100 | | 101 | | // @dev set the referral code for a trader 102 | | // @param _account the address of the trader 103 | | // @param _code the referral code to set to 104 | | function setTraderReferralCode(address _account, bytes32 _code) external override onlyHandler { 105 | | _setTraderReferralCode(_account, _code); 106 | | } 107 | | 108 | | // @dev set the referral code for a trader 109 | | // @param _code the referral code to set to 110 | | function setTraderReferralCodeByUser(bytes32 _code) external { 111 | | _setTraderReferralCode(msg.sender, _code); 112 | | } 113 | | 114 | | // @dev register a referral code 115 | | // @param _code the referral code to register 116 | | function registerCode(bytes32 _code) external { 117 | | require(_code != bytes32(0), "ReferralStorage: invalid _code"); 118 | | require(codeOwners[_code] == address(0), "ReferralStorage: code already exists"); 119 | | 120 | | codeOwners[_code] = msg.sender; 121 | | emit RegisterCode(msg.sender, _code); 122 | | } 123 | | 124 | | // @dev for affiliates to set a new owner for a referral code they own 125 | | // @param _code the referral code 126 | | // @param _newAccount the new owner 127 | | function setCodeOwner(bytes32 _code, address _newAccount) external { 128 | | require(_code != bytes32(0), "ReferralStorage: invalid _code"); 129 | | 130 | | address account = codeOwners[_code]; 131 | | require(msg.sender == account, "ReferralStorage: forbidden"); 132 | | 133 | | codeOwners[_code] = _newAccount; 134 | | emit SetCodeOwner(msg.sender, _newAccount, _code); 135 | | } 136 | | 137 | | // @dev set the owner of a referral code 138 | | // @param _code the referral code 139 | | // @param _newAccount the new owner 140 | | function govSetCodeOwner(bytes32 _code, address _newAccount) external override onlyGov { 141 | | require(_code != bytes32(0), "ReferralStorage: invalid _code"); 142 | | 143 | | codeOwners[_code] = _newAccount; 144 | | emit GovSetCodeOwner(_code, _newAccount); 145 | | } 146 | | 147 | | // @dev get the referral info for a trader 148 | | // @param _account the address of the trader 149 | | function getTraderReferralInfo(address _account) external override view returns (bytes32, address) { 150 | | bytes32 code = traderReferralCodes[_account]; 151 | | address referrer; 152 | | if (code != bytes32(0)) { 153 | | referrer = codeOwners[code]; 154 | | } 155 | | return (code, referrer); 156 | | } 157 | | 158 | | // @dev set the referral code for a trader 159 | | // @param _account the address of the trader 160 | | // @param _code the referral code 161 | | function _setTraderReferralCode(address _account, bytes32 _code) private { 162 | | traderReferralCodes[_account] = _code; 163 | | emit SetTraderReferralCode(_account, _code); 164 | | } 165 | | } 166 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/mock/WNT.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | | 7 | | // @title WNT 8 | | // @dev similar implementation as WETH but since some networks 9 | | // might have a different native token we use WNT for a more general reference name 10 | * | contract WNT is ERC20 { 11 | | constructor() ERC20("Wrapped Native Token", "WNT") {} 12 | | 13 | | error TransferFailed(address account, uint256 amount); 14 | | 15 | | // @dev mint WNT by depositing the native token 16 | * | function deposit() external payable { 17 | * | _mint(msg.sender, msg.value); 18 | | } 19 | | 20 | | // @dev withdraw the native token by burning WNT 21 | | // @param amount the amount to withdraw 22 | * | function withdraw(uint256 amount) external { 23 | * | _burn(msg.sender, amount); 24 | * | (bool success, ) = msg.sender.call{ value: amount }(""); 25 | * | if (!success) { 26 | | revert TransferFailed(msg.sender, amount); 27 | | } 28 | | } 29 | | 30 | | // @dev mint tokens to an account 31 | | // @param account the account to mint to 32 | | // @param amount the amount of tokens to mint 33 | | function mint(address account, uint256 amount) external { 34 | | _mint(account, amount); 35 | | } 36 | | 37 | | // @dev burn tokens from an account 38 | | // @param account the account to burn tokens for 39 | | // @param amount the amount of tokens to burn 40 | | function burn(address account, uint256 amount) external { 41 | | _burn(account, amount); 42 | | } 43 | | } 44 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/nonce/NonceUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | 8 | | // @title NonceUtils 9 | | // @dev Library to keep track of an incrementing nonce value 10 | * | library NonceUtils { 11 | | // @dev get the current nonce value 12 | | // @param dataStore DataStore 13 | | function getCurrentNonce(DataStore dataStore) internal view returns (uint256) { 14 | | return dataStore.getUint(Keys.NONCE); 15 | | } 16 | | 17 | | // @dev increment the current nonce value 18 | | // @param dataStore DataStore 19 | | // @return the new nonce value 20 | * | function incrementNonce(DataStore dataStore) internal returns (uint256) { 21 | * | return dataStore.incrementUint(Keys.NONCE, 1); 22 | | } 23 | | 24 | | // @dev convenience function to create a bytes32 hash using the next nonce 25 | | // it would be possible to use the nonce directly as an ID / key 26 | | // however, for positions the key is a bytes32 value based on a hash of 27 | | // the position values 28 | | // so bytes32 is used instead for a standard key type 29 | | // @param dataStore DataStore 30 | | // @return bytes32 hash using the next nonce value 31 | * | function getNextKey(DataStore dataStore) internal returns (bytes32) { 32 | * | uint256 nonce = incrementNonce(dataStore); 33 | * | bytes32 key = keccak256(abi.encode(address(dataStore), nonce)); 34 | | 35 | * | return key; 36 | | } 37 | | } 38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkDataStreamProvider.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | import "./IOracleProvider.sol"; 8 | | import "./IChainlinkDataStreamVerifier.sol"; 9 | | import "../utils/Precision.sol"; 10 | | import "../chain/Chain.sol"; 11 | | 12 | * | contract ChainlinkDataStreamProvider is IOracleProvider { 13 | | 14 | | DataStore public immutable dataStore; 15 | | address public immutable oracle; 16 | | IChainlinkDataStreamVerifier public immutable verifier; 17 | | 18 | | // bid: min price, highest buy price 19 | | // ask: max price, lowest sell price 20 | | struct Report { 21 | | bytes32 feedId; // The feed ID the report has data for 22 | | uint32 validFromTimestamp; // Earliest timestamp for which price is applicable 23 | | uint32 observationsTimestamp; // Latest timestamp for which price is applicable 24 | | uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (WETH/ETH) 25 | | uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK 26 | | uint32 expiresAt; // Latest timestamp where the report can be verified onchain 27 | | int192 price; // DON consensus median price, carried to 8 decimal places 28 | | int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation 29 | | int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation 30 | | } 31 | | 32 | | modifier onlyOracle() { 33 | | if (msg.sender != oracle) { 34 | | revert Errors.Unauthorized(msg.sender, "Oracle"); 35 | | } 36 | | _; 37 | | } 38 | | 39 | | constructor( 40 | | DataStore _dataStore, 41 | | address _oracle, 42 | | IChainlinkDataStreamVerifier _verifier 43 | | ) { 44 | | dataStore = _dataStore; 45 | | oracle = _oracle; 46 | | verifier = _verifier; 47 | | } 48 | | 49 | | function getOraclePrice( 50 | | address token, 51 | | bytes memory data 52 | | ) external onlyOracle returns (OracleUtils.ValidatedPrice memory) { 53 | | 54 | | bytes32 feedId = dataStore.getBytes32(Keys.dataStreamIdKey(token)); 55 | | if (feedId == bytes32(0)) { 56 | | revert Errors.EmptyDataStreamFeedId(token); 57 | | } 58 | | 59 | | bytes memory payloadParameter = _getPayloadParameter(); 60 | | bytes memory verifierResponse = verifier.verify(data, payloadParameter); 61 | | 62 | | Report memory report = abi.decode(verifierResponse, (Report)); 63 | | 64 | | if (feedId != report.feedId) { 65 | | revert Errors.InvalidDataStreamFeedId(token, report.feedId, feedId); 66 | | } 67 | | 68 | | if (report.bid <= 0 || report.ask <= 0) { 69 | | revert Errors.InvalidDataStreamPrices(token, report.bid, report.ask); 70 | | } 71 | | 72 | | if (report.bid > report.ask) { 73 | | revert Errors.InvalidDataStreamBidAsk(token, report.bid, report.ask); 74 | | } 75 | | 76 | | uint256 precision = _getDataStreamMultiplier(token); 77 | | uint256 adjustedBidPrice = Precision.mulDiv(uint256(uint192(report.bid)), precision, Precision.FLOAT_PRECISION); 78 | | uint256 adjustedAskPrice = Precision.mulDiv(uint256(uint192(report.ask)), precision, Precision.FLOAT_PRECISION); 79 | | 80 | | return OracleUtils.ValidatedPrice({ 81 | | token: token, 82 | | min: adjustedBidPrice, 83 | | max: adjustedAskPrice, 84 | | timestamp: report.observationsTimestamp, 85 | | provider: address(this) 86 | | }); 87 | | } 88 | | 89 | | function _getDataStreamMultiplier(address token) internal view returns (uint256) { 90 | | uint256 multiplier = dataStore.getUint(Keys.dataStreamMultiplierKey(token)); 91 | | 92 | | if (multiplier == 0) { 93 | | revert Errors.EmptyDataStreamMultiplier(token); 94 | | } 95 | | 96 | | return multiplier; 97 | | } 98 | | 99 | | function _getPayloadParameter() internal view returns (bytes memory) { 100 | | // LINK token address 101 | | address feeToken = dataStore.getAddress(Keys.CHAINLINK_PAYMENT_TOKEN); 102 | | 103 | | if (feeToken == address(0)) { 104 | | revert Errors.EmptyChainlinkPaymentToken(); 105 | | } 106 | | 107 | | return abi.encode(feeToken); 108 | | } 109 | | } 110 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkPriceFeedProvider.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | import "./IOracleProvider.sol"; 8 | | import "./ChainlinkPriceFeedUtils.sol"; 9 | | 10 | * | contract ChainlinkPriceFeedProvider is IOracleProvider { 11 | | DataStore public immutable dataStore; 12 | | 13 | | constructor(DataStore _dataStore) { 14 | | dataStore = _dataStore; 15 | | } 16 | | 17 | | // @dev the timestamp returned is based on the current blockchain timestamp 18 | | // this is because Chainlink on-chain price feeds have a lower update frequency 19 | | // if a Chainlink on-chain price feed is used, it is assumed that the feed 20 | | // is sufficiently updated for the intended usage 21 | | // 22 | | // if an on-chain Chainlink price is used together with other price feeds 23 | | // and if the timestamp of the other price feeds are older, this could cause 24 | | // a MaxTimestampRangeExceeded error 25 | | // if this occurs, the MAX_TIMESTAMP_RANGE value may need to be increased 26 | | function getOraclePrice( 27 | | address token, 28 | | bytes memory /* data */ 29 | | ) external view returns (OracleUtils.ValidatedPrice memory) { 30 | | (bool hasPriceFeed, uint256 price) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token); 31 | | 32 | | if (!hasPriceFeed) { 33 | | revert Errors.EmptyChainlinkPriceFeed(token); 34 | | } 35 | | 36 | | uint256 stablePrice = dataStore.getUint(Keys.stablePriceKey(token)); 37 | | 38 | | Price.Props memory priceProps; 39 | | 40 | | if (stablePrice > 0) { 41 | | priceProps = Price.Props( 42 | | price < stablePrice ? price : stablePrice, 43 | | price < stablePrice ? stablePrice : price 44 | | ); 45 | | } else { 46 | | priceProps = Price.Props( 47 | | price, 48 | | price 49 | | ); 50 | | } 51 | | 52 | | return OracleUtils.ValidatedPrice({ 53 | | token: token, 54 | | min: priceProps.min, 55 | | max: priceProps.max, 56 | | timestamp: Chain.currentTimestamp(), 57 | | provider: address(this) 58 | | }); 59 | | } 60 | | } 61 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/ChainlinkPriceFeedUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../chain/Chain.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../data/Keys.sol"; 8 | | import "../utils/Precision.sol"; 9 | | 10 | | import "./IPriceFeed.sol"; 11 | | 12 | | // @title ChainlinkPriceFeedProviderUtils 13 | | // @dev Library for Chainlink price feed 14 | * | library ChainlinkPriceFeedUtils { 15 | | // there is a small risk of stale pricing due to latency in price updates or if the chain is down 16 | | // this is meant to be for temporary use until low latency price feeds are supported for all tokens 17 | | function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) { 18 | | address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token)); 19 | | if (priceFeedAddress == address(0)) { 20 | | return (false, 0); 21 | | } 22 | | 23 | | IPriceFeed priceFeed = IPriceFeed(priceFeedAddress); 24 | | 25 | | ( 26 | | /* uint80 roundID */, 27 | | int256 _price, 28 | | /* uint256 startedAt */, 29 | | uint256 timestamp, 30 | | /* uint80 answeredInRound */ 31 | | ) = priceFeed.latestRoundData(); 32 | | 33 | | if (_price <= 0) { 34 | | revert Errors.InvalidFeedPrice(token, _price); 35 | | } 36 | | 37 | | uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token)); 38 | | if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) { 39 | | revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration); 40 | | } 41 | | 42 | | uint256 price = SafeCast.toUint256(_price); 43 | | uint256 precision = getPriceFeedMultiplier(dataStore, token); 44 | | 45 | | uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION); 46 | | 47 | | return (true, adjustedPrice); 48 | | } 49 | | 50 | | // @dev get the multiplier value to convert the internal price feed price to the price of 1 unit of the token 51 | | // represented with 30 decimals 52 | | // for example, if USDC has 6 decimals and a price of 1 USD, one unit of USDC would have a price of 53 | | // 1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24) 54 | | // if the internal price feed has 8 decimals, the price feed price would be 1 * (10 ^ 8) 55 | | // in this case the priceFeedMultiplier should be 10 ^ 46 56 | | // the conversion of the price feed price would be 1 * (10 ^ 8) * (10 ^ 46) / (10 ^ 30) => 1 * (10 ^ 24) 57 | | // formula for decimals for price feed multiplier: 60 - (internal price feed decimals) - (token decimals) 58 | | // 59 | | // @param dataStore DataStore 60 | | // @param token the token to get the price feed multiplier for 61 | | // @return the price feed multipler 62 | | function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) { 63 | | uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token)); 64 | | 65 | | if (multiplier == 0) { 66 | | revert Errors.EmptyChainlinkPriceFeedMultiplier(token); 67 | | } 68 | | 69 | | return multiplier; 70 | | } 71 | | } 72 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/GmOracleProvider.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 7 | | 8 | | import "../role/RoleModule.sol"; 9 | | 10 | | import "./OracleStore.sol"; 11 | | import "./OracleUtils.sol"; 12 | | import "./IPriceFeed.sol"; 13 | | import "../price/Price.sol"; 14 | | import "./GmOracleUtils.sol"; 15 | | import "./IOracleProvider.sol"; 16 | | 17 | | import "../chain/Chain.sol"; 18 | | import "../data/Keys.sol"; 19 | | import "../data/DataStore.sol"; 20 | | import "../event/EventEmitter.sol"; 21 | | import "../event/EventUtils.sol"; 22 | | 23 | | import "../utils/Bits.sol"; 24 | | import "../utils/Array.sol"; 25 | | import "../utils/Precision.sol"; 26 | | import "../utils/Cast.sol"; 27 | | import "../utils/Uint256Mask.sol"; 28 | | 29 | | // @title Oracle 30 | | // @dev Contract to validate and store signed values 31 | | // Some calculations e.g. calculating the size in tokens for a position 32 | | // may not work with zero / negative prices 33 | | // as a result, zero / negative prices are considered empty / invalid 34 | | // A market may need to be manually settled in this case 35 | * | contract GmOracleProvider is RoleModule, IOracleProvider { 36 | | using Price for Price.Props; 37 | | using Uint256Mask for Uint256Mask.Mask; 38 | | 39 | | uint256 public constant SIGNER_INDEX_LENGTH = 16; 40 | | // subtract 1 as the first slot is used to store number of signers 41 | | uint256 public constant MAX_SIGNERS = 256 / SIGNER_INDEX_LENGTH - 1; 42 | | // signer indexes are recorded in a signerIndexFlags uint256 value to check for uniqueness 43 | | uint256 public constant MAX_SIGNER_INDEX = 256; 44 | | 45 | | DataStore public immutable dataStore; 46 | | OracleStore public immutable oracleStore; 47 | | 48 | | constructor( 49 | | RoleStore _roleStore, 50 | | DataStore _dataStore, 51 | | OracleStore _oracleStore 52 | | ) RoleModule(_roleStore) { 53 | | dataStore = _dataStore; 54 | | oracleStore = _oracleStore; 55 | | } 56 | | 57 | | // @dev Oracle prices are signed as a value together with a precision, this allows 58 | | // prices to be compacted as uint32 values. 59 | | // 60 | | // The signed prices represent the price of one unit of the token using a value 61 | | // with 30 decimals of precision. 62 | | // 63 | | // Representing the prices in this way allows for conversions between token amounts 64 | | // and fiat values to be simplified, e.g. to calculate the fiat value of a given 65 | | // number of tokens the calculation would just be: `token amount * oracle price`, 66 | | // to calculate the token amount for a fiat value it would be: `fiat value / oracle price`. 67 | | // 68 | | // The trade-off of this simplicity in calculation is that tokens with a small USD 69 | | // price and a lot of decimals may have precision issues it is also possible that 70 | | // a token's price changes significantly and results in requiring higher precision. 71 | | // 72 | | // ## Example 1 73 | | // 74 | | // The price of ETH is 5000, and ETH has 18 decimals. 75 | | // 76 | | // The price of one unit of ETH is `5000 / (10 ^ 18), 5 * (10 ^ -15)`. 77 | | // 78 | | // To handle the decimals, multiply the value by `(10 ^ 30)`. 79 | | // 80 | | // Price would be stored as `5000 / (10 ^ 18) * (10 ^ 30) => 5000 * (10 ^ 12)`. 81 | | // 82 | | // For gas optimization, these prices are sent to the oracle in the form of a uint8 83 | | // decimal multiplier value and uint32 price value. 84 | | // 85 | | // If the decimal multiplier value is set to 8, the uint32 value would be `5000 * (10 ^ 12) / (10 ^ 8) => 5000 * (10 ^ 4)`. 86 | | // 87 | | // With this config, ETH prices can have a maximum value of `(2 ^ 32) / (10 ^ 4) => 4,294,967,296 / (10 ^ 4) => 429,496.7296` with 4 decimals of precision. 88 | | // 89 | | // ## Example 2 90 | | // 91 | | // The price of BTC is 60,000, and BTC has 8 decimals. 92 | | // 93 | | // The price of one unit of BTC is `60,000 / (10 ^ 8), 6 * (10 ^ -4)`. 94 | | // 95 | | // Price would be stored as `60,000 / (10 ^ 8) * (10 ^ 30) => 6 * (10 ^ 26) => 60,000 * (10 ^ 22)`. 96 | | // 97 | | // BTC prices maximum value: `(2 ^ 32) / (10 ^ 2) => 4,294,967,296 / (10 ^ 2) => 42,949,672.96`. 98 | | // 99 | | // Decimals of precision: 2. 100 | | // 101 | | // ## Example 3 102 | | // 103 | | // The price of USDC is 1, and USDC has 6 decimals. 104 | | // 105 | | // The price of one unit of USDC is `1 / (10 ^ 6), 1 * (10 ^ -6)`. 106 | | // 107 | | // Price would be stored as `1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)`. 108 | | // 109 | | // USDC prices maximum value: `(2 ^ 64) / (10 ^ 6) => 4,294,967,296 / (10 ^ 6) => 4294.967296`. 110 | | // 111 | | // Decimals of precision: 6. 112 | | // 113 | | // ## Example 4 114 | | // 115 | | // The price of DG is 0.00000001, and DG has 18 decimals. 116 | | // 117 | | // The price of one unit of DG is `0.00000001 / (10 ^ 18), 1 * (10 ^ -26)`. 118 | | // 119 | | // Price would be stored as `1 * (10 ^ -26) * (10 ^ 30) => 1 * (10 ^ 3)`. 120 | | // 121 | | // DG prices maximum value: `(2 ^ 64) / (10 ^ 11) => 4,294,967,296 / (10 ^ 11) => 0.04294967296`. 122 | | // 123 | | // Decimals of precision: 11. 124 | | // 125 | | // ## Decimal Multiplier 126 | | // 127 | | // The formula to calculate what the decimal multiplier value should be set to: 128 | | // 129 | | // Decimals: 30 - (token decimals) - (number of decimals desired for precision) 130 | | // 131 | | // - ETH: 30 - 18 - 4 => 8 132 | | // - BTC: 30 - 8 - 2 => 20 133 | | // - USDC: 30 - 6 - 6 => 18 134 | | // - DG: 30 - 18 - 11 => 1 135 | | function getOraclePrice( 136 | | address token, 137 | | bytes memory data 138 | | ) external view returns (OracleUtils.ValidatedPrice memory) { 139 | | GmOracleUtils.Report memory report = abi.decode(data, (GmOracleUtils.Report)); 140 | | address[] memory signers = _getSigners(report.signerInfo); 141 | | 142 | | if (report.minOracleBlockNumber > report.maxOracleBlockNumber) { 143 | | revert Errors.GmInvalidMinMaxBlockNumber(report.minOracleBlockNumber, report.maxOracleBlockNumber); 144 | | } 145 | | 146 | | if (report.maxOracleBlockNumber >= Chain.currentBlockNumber()) { 147 | | revert Errors.GmInvalidBlockNumber(report.maxOracleBlockNumber, Chain.currentBlockNumber()); 148 | | } 149 | | 150 | | bytes32 tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(token)); 151 | | 152 | | for (uint256 i = 0; i < signers.length; i++) { 153 | | if (i == 0) { continue; } 154 | | 155 | | // validate that minPrices are sorted in ascending order 156 | | if (report.minPrices[i - 1] > report.minPrices[i]) { 157 | | revert Errors.GmMinPricesNotSorted(token, report.minPrices[i], report.minPrices[i - 1]); 158 | | } 159 | | 160 | | // validate that maxPrices are sorted in ascending order 161 | | if (report.maxPrices[i - 1] > report.maxPrices[i]) { 162 | | revert Errors.GmMaxPricesNotSorted(token, report.maxPrices[i], report.maxPrices[i - 1]); 163 | | } 164 | | } 165 | | 166 | | bytes32 salt = _getSalt(); 167 | | 168 | | for (uint256 i = 0; i < signers.length; i++) { 169 | | uint256 minPrice = report.minPrices[i]; 170 | | uint256 maxPrice = report.maxPrices[i]; 171 | | 172 | | if (minPrice > maxPrice) { 173 | | revert Errors.InvalidGmSignerMinMaxPrice(minPrice, maxPrice); 174 | | } 175 | | 176 | | GmOracleUtils.validateSigner( 177 | | salt, 178 | | report, 179 | | token, 180 | | minPrice, 181 | | maxPrice, 182 | | tokenOracleType, 183 | | report.signatures[i], 184 | | signers[i] 185 | | ); 186 | | } 187 | | 188 | | uint256 medianMinPrice = Array.getMedian(report.minPrices) * (10 ** report.precision); 189 | | uint256 medianMaxPrice = Array.getMedian(report.maxPrices) * (10 ** report.precision); 190 | | 191 | | if (medianMinPrice == 0 || medianMaxPrice == 0) { 192 | | revert Errors.InvalidGmOraclePrice(token); 193 | | } 194 | | 195 | | if (medianMinPrice > medianMaxPrice) { 196 | | revert Errors.InvalidGmMedianMinMaxPrice(medianMinPrice, medianMaxPrice); 197 | | } 198 | | 199 | | return OracleUtils.ValidatedPrice({ 200 | | token: token, 201 | | min: medianMinPrice, 202 | | max: medianMaxPrice, 203 | | timestamp: report.oracleTimestamp, 204 | | provider: address(this) 205 | | }); 206 | | } 207 | | 208 | | function _getSigners( 209 | | uint256 signerInfo 210 | | ) internal view returns (address[] memory) { 211 | | // first 16 bits of signer info contains the number of signers 212 | | address[] memory signers = new address[](signerInfo & Bits.BITMASK_16); 213 | | 214 | | if (signers.length < dataStore.getUint(Keys.MIN_ORACLE_SIGNERS)) { 215 | | revert Errors.GmMinOracleSigners(signers.length, dataStore.getUint(Keys.MIN_ORACLE_SIGNERS)); 216 | | } 217 | | 218 | | if (signers.length > MAX_SIGNERS) { 219 | | revert Errors.GmMaxOracleSigners(signers.length, MAX_SIGNERS); 220 | | } 221 | | 222 | | Uint256Mask.Mask memory signerIndexMask; 223 | | 224 | | for (uint256 i; i < signers.length; i++) { 225 | | uint256 signerIndex = signerInfo >> (16 + 16 * i) & Bits.BITMASK_16; 226 | | 227 | | if (signerIndex >= MAX_SIGNER_INDEX) { 228 | | revert Errors.GmMaxSignerIndex(signerIndex, MAX_SIGNER_INDEX); 229 | | } 230 | | 231 | | signerIndexMask.validateUniqueAndSetIndex(signerIndex, "signerIndex"); 232 | | 233 | | signers[i] = oracleStore.getSigner(signerIndex); 234 | | 235 | | if (signers[i] == address(0)) { 236 | | revert Errors.GmEmptySigner(signerIndex); 237 | | } 238 | | } 239 | | 240 | | return signers; 241 | | } 242 | | 243 | | // it might be possible for the block.chainid to change due to a fork or similar 244 | | // for this reason, this salt is not cached 245 | | function _getSalt() internal view returns (bytes32) { 246 | | return keccak256(abi.encode(block.chainid, "xget-oracle-v1")); 247 | | } 248 | | } 249 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/GmOracleUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; 6 | | import "../error/Errors.sol"; 7 | | 8 | | // @title GmOracleUtils 9 | | // @dev Library for GmOracle functions 10 | * | library GmOracleUtils { 11 | | struct Report { 12 | | address token; 13 | | uint256 signerInfo; 14 | | uint256 precision; 15 | | uint256 minOracleBlockNumber; 16 | | uint256 maxOracleBlockNumber; 17 | | uint256 oracleTimestamp; 18 | | bytes32 blockHash; 19 | | uint256[] minPrices; 20 | | uint256[] maxPrices; 21 | | bytes[] signatures; 22 | | } 23 | | 24 | | // @dev validate the signer of a price 25 | | // before calling this function, the expectedSigner should be validated to 26 | | // ensure that it is not the zero address 27 | | // @param report the oracle Report data 28 | | // @param token the token used for the signed message hash 29 | | // @param minPrice the min price used for the signed message hash 30 | | // @param maxPrice the max price used for the signed message hash 31 | | // @param tokenOracleType the token oracle type used for the signed message hash 32 | | // @param signature the signer's signature 33 | | // @param expectedSigner the address of the expected signer 34 | | function validateSigner( 35 | | bytes32 salt, 36 | | Report memory report, 37 | | address token, 38 | | uint256 minPrice, 39 | | uint256 maxPrice, 40 | | bytes32 tokenOracleType, 41 | | bytes memory signature, 42 | | address expectedSigner 43 | | ) internal pure { 44 | | bytes32 digest = ECDSA.toEthSignedMessageHash( 45 | | keccak256(abi.encode( 46 | | salt, 47 | | report.minOracleBlockNumber, 48 | | report.maxOracleBlockNumber, 49 | | report.oracleTimestamp, 50 | | report.blockHash, 51 | | token, 52 | | tokenOracleType, 53 | | 10 ** report.precision, 54 | | minPrice, 55 | | maxPrice 56 | | )) 57 | | ); 58 | | 59 | | address recoveredSigner = ECDSA.recover(digest, signature); 60 | | if (recoveredSigner != expectedSigner) { 61 | | revert Errors.InvalidGmSignature(recoveredSigner, expectedSigner); 62 | | } 63 | | } 64 | | } 65 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IChainlinkDataStreamVerifier.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | interface IChainlinkDataStreamVerifier { 6 | | /** 7 | | * @notice Verifies that the data encoded has been signed 8 | | * correctly by routing to the correct verifier, and bills the user if applicable. 9 | | * @param payload The encoded data to be verified, including the signed 10 | | * report. 11 | | * @param parameterPayload fee metadata for billing. For the current implementation this is just the abi-encoded fee token ERC-20 address 12 | | * @return verifierResponse The encoded report from the verifier. 13 | | */ 14 | | function verify( 15 | | bytes calldata payload, 16 | | bytes calldata parameterPayload 17 | | ) external payable returns (bytes memory verifierResponse); 18 | | } 19 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IOracleProvider.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./OracleUtils.sol"; 6 | | 7 | | // @title IOracleProvider 8 | | // @dev Interface for an oracle provider 9 | | interface IOracleProvider { 10 | | function getOraclePrice( 11 | | address token, 12 | | bytes memory data 13 | | ) external returns (OracleUtils.ValidatedPrice memory); 14 | | } 15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/IPriceFeed.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title IPriceFeed 6 | | // @dev Interface for a price feed 7 | | interface IPriceFeed { 8 | | function latestRoundData() external view returns ( 9 | | uint80 roundId, 10 | | int256 answer, 11 | | uint256 startedAt, 12 | | uint256 updatedAt, 13 | | uint80 answeredInRound 14 | | ); 15 | | } 16 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/Oracle.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 7 | | import { AggregatorV2V3Interface } from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol"; 8 | | 9 | | import "../role/RoleModule.sol"; 10 | | 11 | | import "./OracleStore.sol"; 12 | | import "./OracleUtils.sol"; 13 | | import "./IPriceFeed.sol"; 14 | | import "./IOracleProvider.sol"; 15 | | import "./ChainlinkPriceFeedUtils.sol"; 16 | | import "../price/Price.sol"; 17 | | 18 | | import "../chain/Chain.sol"; 19 | | import "../data/DataStore.sol"; 20 | | import "../data/Keys.sol"; 21 | | import "../event/EventEmitter.sol"; 22 | | import "../event/EventUtils.sol"; 23 | | 24 | | import "../utils/Bits.sol"; 25 | | import "../utils/Array.sol"; 26 | | import "../utils/Precision.sol"; 27 | | import "../utils/Cast.sol"; 28 | | import "../utils/Uint256Mask.sol"; 29 | | 30 | | // @title Oracle 31 | | // @dev Contract to validate and store signed values 32 | | // Some calculations e.g. calculating the size in tokens for a position 33 | | // may not work with zero / negative prices 34 | | // as a result, zero / negative prices are considered empty / invalid 35 | | // A market may need to be manually settled in this case 36 | * | contract Oracle is RoleModule { 37 | | using EnumerableSet for EnumerableSet.AddressSet; 38 | | using EnumerableValues for EnumerableSet.AddressSet; 39 | | using Price for Price.Props; 40 | | using Uint256Mask for Uint256Mask.Mask; 41 | | 42 | | using EventUtils for EventUtils.AddressItems; 43 | | using EventUtils for EventUtils.UintItems; 44 | | using EventUtils for EventUtils.IntItems; 45 | | using EventUtils for EventUtils.BoolItems; 46 | | using EventUtils for EventUtils.Bytes32Items; 47 | | using EventUtils for EventUtils.BytesItems; 48 | | using EventUtils for EventUtils.StringItems; 49 | | 50 | | DataStore public immutable dataStore; 51 | | EventEmitter public immutable eventEmitter; 52 | | AggregatorV2V3Interface public immutable sequencerUptimeFeed; 53 | | 54 | | // tokensWithPrices stores the tokens with prices that have been set 55 | | // this is used in clearAllPrices to help ensure that all token prices 56 | | // set in setPrices are cleared after use 57 | | EnumerableSet.AddressSet internal tokensWithPrices; 58 | | mapping(address => Price.Props) public primaryPrices; 59 | | 60 | * | uint256 public minTimestamp; 61 | * | uint256 public maxTimestamp; 62 | | 63 | | constructor( 64 | | RoleStore _roleStore, 65 | | DataStore _dataStore, 66 | | EventEmitter _eventEmitter, 67 | | AggregatorV2V3Interface _sequencerUptimeFeed 68 | | ) RoleModule(_roleStore) { 69 | | dataStore = _dataStore; 70 | | eventEmitter = _eventEmitter; 71 | | sequencerUptimeFeed = _sequencerUptimeFeed; 72 | | } 73 | | 74 | | // this can be used to help ensure that on-chain prices are updated 75 | | // before actions dependent on those on-chain prices are allowed 76 | | // additionally, this can also be used to provide a grace period for 77 | | // users to top up collateral before liquidations occur 78 | * | function validateSequencerUp() external view { 79 | * | if (address(sequencerUptimeFeed) == address(0)) { 80 | * | return; 81 | | } 82 | | 83 | | ( 84 | | /*uint80 roundID*/, 85 | | int256 answer, 86 | | uint256 startedAt, 87 | | /*uint256 updatedAt*/, 88 | | /*uint80 answeredInRound*/ 89 | | ) = sequencerUptimeFeed.latestRoundData(); 90 | | 91 | | // Answer == 0: Sequencer is up 92 | | // Answer == 1: Sequencer is down 93 | | bool isSequencerUp = answer == 0; 94 | | if (!isSequencerUp) { 95 | | revert Errors.SequencerDown(); 96 | | } 97 | | 98 | | uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION); 99 | | 100 | | // Make sure the grace duration has passed after the 101 | | // sequencer is back up. 102 | | uint256 timeSinceUp = block.timestamp - startedAt; 103 | | if (timeSinceUp <= sequencerGraceDuration) { 104 | | revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration); 105 | | } 106 | | } 107 | | 108 | * | function setPrices( 109 | | OracleUtils.SetPricesParams memory params 110 | * | ) external onlyController { 111 | * | OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false); 112 | | 113 | * | _setPrices(prices); 114 | | } 115 | | 116 | * | function setPricesForAtomicAction( 117 | | OracleUtils.SetPricesParams memory params 118 | * | ) external onlyController { 119 | * | OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true); 120 | | 121 | * | _setPrices(prices); 122 | | } 123 | | 124 | | // @dev set the primary price 125 | | // @param token the token to set the price for 126 | | // @param price the price value to set to 127 | | function setPrimaryPrice(address token, Price.Props memory price) external onlyController { 128 | | _setPrimaryPrice(token, price); 129 | | } 130 | | 131 | | function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController { 132 | | minTimestamp = _minTimestamp; 133 | | maxTimestamp = _maxTimestamp; 134 | | } 135 | | 136 | | // @dev clear all prices 137 | * | function clearAllPrices() external onlyController { 138 | * | uint256 length = tokensWithPrices.length(); 139 | * | for (uint256 i; i < length; i++) { 140 | * | address token = tokensWithPrices.at(0); 141 | * | _removePrimaryPrice(token); 142 | | } 143 | | 144 | * | minTimestamp = 0; 145 | * | maxTimestamp = 0; 146 | | } 147 | | 148 | | // @dev get the length of tokensWithPrices 149 | | // @return the length of tokensWithPrices 150 | | function getTokensWithPricesCount() external view returns (uint256) { 151 | | return tokensWithPrices.length(); 152 | | } 153 | | 154 | | // @dev get the tokens of tokensWithPrices for the specified indexes 155 | | // @param start the start index, the value for this index will be included 156 | | // @param end the end index, the value for this index will not be included 157 | | // @return the tokens of tokensWithPrices for the specified indexes 158 | | function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) { 159 | | return tokensWithPrices.valuesAt(start, end); 160 | | } 161 | | 162 | | // @dev get the primary price of a token 163 | | // @param token the token to get the price for 164 | | // @return the primary price of a token 165 | * | function getPrimaryPrice(address token) external view returns (Price.Props memory) { 166 | * | if (token == address(0)) { return Price.Props(0, 0); } 167 | | 168 | * | Price.Props memory price = primaryPrices[token]; 169 | * | if (price.isEmpty()) { 170 | | revert Errors.EmptyPrimaryPrice(token); 171 | | } 172 | | 173 | * | return price; 174 | | } 175 | | 176 | | function validatePrices( 177 | | OracleUtils.SetPricesParams memory params, 178 | | bool forAtomicAction 179 | | ) external onlyController returns (OracleUtils.ValidatedPrice[] memory) { 180 | | return _validatePrices(params, forAtomicAction); 181 | | } 182 | | 183 | | // @dev validate and set prices 184 | | // @param params OracleUtils.SetPricesParams 185 | * | function _setPrices( 186 | | OracleUtils.ValidatedPrice[] memory prices 187 | * | ) internal returns (OracleUtils.ValidatedPrice[] memory) { 188 | * | if (tokensWithPrices.length() != 0) { 189 | | revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length()); 190 | | } 191 | | 192 | * | if (prices.length == 0) { 193 | | revert Errors.EmptyValidatedPrices(); 194 | | } 195 | | 196 | * | uint256 _minTimestamp = prices[0].timestamp; 197 | * | uint256 _maxTimestamp = prices[0].timestamp; 198 | | 199 | * | for (uint256 i; i < prices.length; i++) { 200 | * | OracleUtils.ValidatedPrice memory validatedPrice = prices[i]; 201 | | 202 | * | _setPrimaryPrice(validatedPrice.token, Price.Props( 203 | * | validatedPrice.min, 204 | * | validatedPrice.max 205 | | )); 206 | | 207 | * | if (validatedPrice.timestamp < _minTimestamp) { 208 | | _minTimestamp = validatedPrice.timestamp; 209 | | } 210 | | 211 | * | if (validatedPrice.timestamp > _maxTimestamp) { 212 | | _maxTimestamp = validatedPrice.timestamp; 213 | | } 214 | | 215 | * | _emitOraclePriceUpdated( 216 | * | validatedPrice.token, 217 | * | validatedPrice.min, 218 | * | validatedPrice.max, 219 | * | validatedPrice.timestamp, 220 | * | validatedPrice.provider 221 | | ); 222 | | } 223 | | 224 | * | uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE); 225 | * | if (_maxTimestamp - _minTimestamp > maxRange) { 226 | | revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange); 227 | | } 228 | | 229 | * | minTimestamp = _minTimestamp; 230 | * | maxTimestamp = _maxTimestamp; 231 | | 232 | * | return prices; 233 | | } 234 | | 235 | * | function _validatePrices( 236 | | OracleUtils.SetPricesParams memory params, 237 | | bool forAtomicAction 238 | * | ) internal returns (OracleUtils.ValidatedPrice[] memory) { 239 | * | if (params.tokens.length != params.providers.length) { 240 | | revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length); 241 | | } 242 | | 243 | * | if (params.tokens.length != params.data.length) { 244 | | revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length); 245 | | } 246 | | 247 | * | OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length); 248 | | 249 | * | uint256 maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE); 250 | * | uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR); 251 | | 252 | * | for (uint256 i; i < params.tokens.length; i++) { 253 | * | address provider = params.providers[i]; 254 | | 255 | * | if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(provider))) { 256 | | revert Errors.InvalidOracleProvider(provider); 257 | | } 258 | | 259 | * | address token = params.tokens[i]; 260 | | 261 | * | bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(provider)); 262 | | 263 | | // if the action is atomic then only validate that the provider is an 264 | | // atomic provider 265 | | // else, validate that the provider matches the oracleProviderForToken 266 | | // 267 | | // since for atomic actions, any atomic provider can be used, it is 268 | | // recommended that only one atomic provider is configured per token 269 | | // otherwise there is a risk that if there is a difference in pricing 270 | | // between atomic oracle providers for a token, a user could use that 271 | | // to gain a profit by alternating actions between the two atomic 272 | | // providers 273 | * | if (forAtomicAction) { 274 | * | if (!isAtomicProvider) { 275 | | revert Errors.NonAtomicOracleProvider(provider); 276 | | } 277 | * | } else { 278 | * | address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(token)); 279 | * | if (provider != expectedProvider) { 280 | | revert Errors.InvalidOracleProviderForToken(provider, expectedProvider); 281 | | } 282 | | } 283 | | 284 | * | bytes memory data = params.data[i]; 285 | | 286 | * | OracleUtils.ValidatedPrice memory validatedPrice = IOracleProvider(provider).getOraclePrice( 287 | * | token, 288 | * | data 289 | | ); 290 | | 291 | | // for atomic providers, the timestamp will be the current block's timestamp 292 | | // the timestamp should not be adjusted 293 | * | if (!isAtomicProvider) { 294 | | uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(provider, token)); 295 | | validatedPrice.timestamp -= timestampAdjustment; 296 | | } 297 | | 298 | * | if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) { 299 | | revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp()); 300 | | } 301 | | 302 | | // for atomic providers, assume that Chainlink would be the main provider 303 | | // so it would be redundant to re-fetch the Chainlink price for validation 304 | * | if (!isAtomicProvider) { 305 | | (bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token); 306 | | 307 | | if (hasRefPrice) { 308 | | _validateRefPrice( 309 | | token, 310 | | validatedPrice.min, 311 | | refPrice, 312 | | maxRefPriceDeviationFactor 313 | | ); 314 | | 315 | | _validateRefPrice( 316 | | token, 317 | | validatedPrice.max, 318 | | refPrice, 319 | | maxRefPriceDeviationFactor 320 | | ); 321 | | } 322 | | } 323 | | 324 | * | prices[i] = validatedPrice; 325 | | } 326 | | 327 | * | return prices; 328 | | } 329 | | 330 | | function _validateRefPrice( 331 | | address token, 332 | | uint256 price, 333 | | uint256 refPrice, 334 | | uint256 maxRefPriceDeviationFactor 335 | | ) internal pure { 336 | | uint256 diff = Calc.diff(price, refPrice); 337 | | uint256 diffFactor = Precision.toFactor(diff, refPrice); 338 | | 339 | | if (diffFactor > maxRefPriceDeviationFactor) { 340 | | revert Errors.MaxRefPriceDeviationExceeded( 341 | | token, 342 | | price, 343 | | refPrice, 344 | | maxRefPriceDeviationFactor 345 | | ); 346 | | } 347 | | } 348 | | 349 | * | function _setPrimaryPrice(address token, Price.Props memory price) internal { 350 | * | if (price.min > price.max) { 351 | | revert Errors.InvalidMinMaxForPrice(token, price.min, price.max); 352 | | } 353 | | 354 | * | Price.Props memory existingPrice = primaryPrices[token]; 355 | | 356 | * | if (!existingPrice.isEmpty()) { 357 | | revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max); 358 | | } 359 | | 360 | * | primaryPrices[token] = price; 361 | * | tokensWithPrices.add(token); 362 | | } 363 | | 364 | * | function _removePrimaryPrice(address token) internal { 365 | * | delete primaryPrices[token]; 366 | * | tokensWithPrices.remove(token); 367 | | } 368 | | 369 | * | function _emitOraclePriceUpdated( 370 | | address token, 371 | | uint256 minPrice, 372 | | uint256 maxPrice, 373 | | uint256 timestamp, 374 | | address provider 375 | * | ) internal { 376 | * | EventUtils.EventLogData memory eventData; 377 | | 378 | * | eventData.addressItems.initItems(2); 379 | * | eventData.addressItems.setItem(0, "token", token); 380 | * | eventData.addressItems.setItem(1, "provider", provider); 381 | | 382 | * | eventData.uintItems.initItems(3); 383 | * | eventData.uintItems.setItem(0, "minPrice", minPrice); 384 | * | eventData.uintItems.setItem(1, "maxPrice", maxPrice); 385 | * | eventData.uintItems.setItem(2, "timestamp", timestamp); 386 | | 387 | * | eventEmitter.emitEventLog1( 388 | | "OraclePriceUpdate", 389 | * | Cast.toBytes32(token), 390 | * | eventData 391 | | ); 392 | | } 393 | | } 394 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleModule.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./Oracle.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | 8 | | // @title OracleModule 9 | | // @dev Provides convenience functions for interacting with the Oracle 10 | | contract OracleModule { 11 | * | Oracle public immutable oracle; 12 | | 13 | | constructor(Oracle _oracle) { 14 | | oracle = _oracle; 15 | | } 16 | | 17 | | // @dev sets oracle prices, perform any additional tasks required, 18 | | // and clear the oracle prices after 19 | | // 20 | | // care should be taken to avoid re-entrancy while using this call 21 | | // since re-entrancy could allow functions to be called with prices 22 | | // meant for a different type of transaction 23 | | // the tokensWithPrices.length check in oracle.setPrices should help 24 | | // mitigate this 25 | | // 26 | | // @param params OracleUtils.SetPricesParams 27 | * | modifier withOraclePrices( 28 | | OracleUtils.SetPricesParams memory params 29 | | ) { 30 | * | oracle.setPrices(params); 31 | | _; 32 | * | oracle.clearAllPrices(); 33 | | } 34 | | 35 | * | modifier withOraclePricesForAtomicAction( 36 | | OracleUtils.SetPricesParams memory params 37 | | ) { 38 | * | oracle.setPricesForAtomicAction(params); 39 | | _; 40 | | oracle.clearAllPrices(); 41 | | } 42 | | 43 | | // @dev set oracle prices for a simulation 44 | | // tokensWithPrices is not set in this function 45 | | // it is possible for withSimulatedOraclePrices to be called and a function 46 | | // using withOraclePrices to be called after 47 | | // or for a function using withOraclePrices to be called and withSimulatedOraclePrices 48 | | // called after 49 | | // this should not cause an issue because this transaction should always revert 50 | | // and any state changes based on simulated prices as well as the setting of simulated 51 | | // prices should not be persisted 52 | | // @param params OracleUtils.SimulatePricesParams 53 | | modifier withSimulatedOraclePrices( 54 | | OracleUtils.SimulatePricesParams memory params 55 | | ) { 56 | | if (params.primaryTokens.length != params.primaryPrices.length) { 57 | | revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length); 58 | | } 59 | | 60 | | for (uint256 i; i < params.primaryTokens.length; i++) { 61 | | address token = params.primaryTokens[i]; 62 | | Price.Props memory price = params.primaryPrices[i]; 63 | | oracle.setPrimaryPrice(token, price); 64 | | } 65 | | 66 | | oracle.setTimestamps(params.minTimestamp, params.maxTimestamp); 67 | | 68 | | _; 69 | | 70 | | revert Errors.EndOfOracleSimulation(); 71 | | } 72 | | } 73 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleStore.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../role/RoleModule.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | import "../event/EventUtils.sol"; 8 | | import "../utils/Cast.sol"; 9 | | 10 | | // @title OracleStore 11 | | // @dev Stores the list of oracle signers 12 | * | contract OracleStore is RoleModule { 13 | | using EnumerableSet for EnumerableSet.AddressSet; 14 | | using EnumerableValues for EnumerableSet.AddressSet; 15 | | 16 | | using EventUtils for EventUtils.AddressItems; 17 | | using EventUtils for EventUtils.UintItems; 18 | | using EventUtils for EventUtils.IntItems; 19 | | using EventUtils for EventUtils.BoolItems; 20 | | using EventUtils for EventUtils.Bytes32Items; 21 | | using EventUtils for EventUtils.BytesItems; 22 | | using EventUtils for EventUtils.StringItems; 23 | | 24 | | EventEmitter public immutable eventEmitter; 25 | | 26 | | EnumerableSet.AddressSet internal signers; 27 | | 28 | | constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) { 29 | | eventEmitter = _eventEmitter; 30 | | } 31 | | 32 | | // @dev adds a signer 33 | | // @param account address of the signer to add 34 | | function addSigner(address account) external onlyController { 35 | | signers.add(account); 36 | | 37 | | EventUtils.EventLogData memory eventData; 38 | | eventData.addressItems.initItems(1); 39 | | eventData.addressItems.setItem(0, "account", account); 40 | | 41 | | eventEmitter.emitEventLog1( 42 | | "SignerAdded", 43 | | Cast.toBytes32(account), 44 | | eventData 45 | | ); 46 | | } 47 | | 48 | | // @dev removes a signer 49 | | // @param account address of the signer to remove 50 | | function removeSigner(address account) external onlyController { 51 | | signers.remove(account); 52 | | 53 | | EventUtils.EventLogData memory eventData; 54 | | eventData.addressItems.initItems(1); 55 | | eventData.addressItems.setItem(0, "account", account); 56 | | 57 | | eventEmitter.emitEventLog1( 58 | | "SignerRemoved", 59 | | Cast.toBytes32(account), 60 | | eventData 61 | | ); 62 | | } 63 | | 64 | | // @dev get the total number of signers 65 | | // @return the total number of signers 66 | | function getSignerCount() external view returns (uint256) { 67 | | return signers.length(); 68 | | } 69 | | 70 | | // @dev get the signer at the specified index 71 | | // @param index the index of the signer to get 72 | | // @return the signer at the specified index 73 | | function getSigner(uint256 index) external view returns (address) { 74 | | return signers.at(index); 75 | | } 76 | | 77 | | // @dev get the signers for the specified indexes 78 | | // @param start the start index, the value for this index will be included 79 | | // @param end the end index, the value for this index will not be included 80 | | // @return the signers for the specified indexes 81 | | function getSigners(uint256 start, uint256 end) external view returns (address[] memory) { 82 | | return signers.valuesAt(start, end); 83 | | } 84 | | } 85 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/oracle/OracleUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/Array.sol"; 6 | | import "../utils/Bits.sol"; 7 | | import "../price/Price.sol"; 8 | | import "../utils/Printer.sol"; 9 | | 10 | | // @title OracleUtils 11 | | // @dev Library for oracle functions 12 | * | library OracleUtils { 13 | | using Array for uint256[]; 14 | | 15 | | struct SetPricesParams { 16 | | address[] tokens; 17 | | address[] providers; 18 | | bytes[] data; 19 | | } 20 | | 21 | | struct ValidatedPrice { 22 | | address token; 23 | | uint256 min; 24 | | uint256 max; 25 | | uint256 timestamp; 26 | | address provider; 27 | | } 28 | | 29 | | struct SimulatePricesParams { 30 | | address[] primaryTokens; 31 | | Price.Props[] primaryPrices; 32 | | uint256 minTimestamp; 33 | | uint256 maxTimestamp; 34 | | } 35 | | 36 | * | function isOracleError(bytes4 errorSelector) internal pure returns (bool) { 37 | * | if (isOracleTimestampError(errorSelector)) { 38 | * | return true; 39 | | } 40 | | 41 | * | if (isEmptyPriceError(errorSelector)) { 42 | | return true; 43 | | } 44 | | 45 | * | return false; 46 | | } 47 | | 48 | * | function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) { 49 | * | if (errorSelector == Errors.EmptyPrimaryPrice.selector) { 50 | | return true; 51 | | } 52 | | 53 | * | return false; 54 | | } 55 | | 56 | * | function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) { 57 | * | if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) { 58 | * | return true; 59 | | } 60 | | 61 | * | if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) { 62 | * | return true; 63 | | } 64 | | 65 | * | return false; 66 | | } 67 | | } 68 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/AutoCancelUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../error/Errors.sol"; 8 | | 9 | * | library AutoCancelUtils { 10 | * | function addAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal { 11 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey); 12 | * | uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore); 13 | * | uint256 count = dataStore.getBytes32Count(listKey); 14 | * | if (count >= maxAutoCancelOrders) { 15 | | revert Errors.MaxAutoCancelOrdersExceeded(count, maxAutoCancelOrders); 16 | | } 17 | | 18 | * | dataStore.addBytes32(listKey, orderKey); 19 | | } 20 | | 21 | * | function removeAutoCancelOrderKey(DataStore dataStore, bytes32 positionKey, bytes32 orderKey) internal { 22 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey); 23 | * | dataStore.removeBytes32(listKey, orderKey); 24 | | } 25 | | 26 | * | function getAutoCancelOrderKeys(DataStore dataStore, bytes32 positionKey) internal view returns (bytes32[] memory) { 27 | * | bytes32 listKey = Keys.autoCancelOrderListKey(positionKey); 28 | * | uint256 maxAutoCancelOrders = getMaxAutoCancelOrders(dataStore); 29 | * | return dataStore.getBytes32ValuesAt(listKey, 0, maxAutoCancelOrders); 30 | | } 31 | | 32 | * | function getMaxAutoCancelOrders(DataStore dataStore) internal view returns (uint256) { 33 | * | return dataStore.getUint(Keys.MAX_AUTO_CANCEL_ORDERS); 34 | | } 35 | | } 36 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/BaseOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./Order.sol"; 6 | | import "../market/Market.sol"; 7 | | 8 | | import "../data/DataStore.sol"; 9 | | import "../event/EventEmitter.sol"; 10 | | import "../referral/IReferralStorage.sol"; 11 | | 12 | | import "../order/OrderVault.sol"; 13 | | import "../order/IBaseOrderUtils.sol"; 14 | | import "../position/PositionUtils.sol"; 15 | | 16 | | import "../oracle/Oracle.sol"; 17 | | import "../swap/SwapHandler.sol"; 18 | | 19 | | // @title Order 20 | | // @dev Library for common order functions used in OrderUtils, IncreaseOrderUtils 21 | | // DecreaseOrderUtils, SwapOrderUtils 22 | * | library BaseOrderUtils { 23 | | using SafeCast for int256; 24 | | using SafeCast for uint256; 25 | | 26 | | using Order for Order.Props; 27 | | using Price for Price.Props; 28 | | 29 | | // @dev ExecuteOrderParams struct used in executeOrder to avoid stack 30 | | // too deep errors 31 | | // 32 | | // @param contracts ExecuteOrderParamsContracts 33 | | // @param key the key of the order to execute 34 | | // @param order the order to execute 35 | | // @param swapPathMarkets the market values of the markets in the swapPath 36 | | // @param minOracleTimestamp the min oracle timestamp 37 | | // @param maxOracleTimestamp the max oracle timestamp 38 | | // @param market market values of the trading market 39 | | // @param keeper the keeper sending the transaction 40 | | // @param startingGas the starting gas 41 | | // @param secondaryOrderType the secondary order type 42 | | struct ExecuteOrderParams { 43 | | ExecuteOrderParamsContracts contracts; 44 | | bytes32 key; 45 | | Order.Props order; 46 | | Market.Props[] swapPathMarkets; 47 | | uint256 minOracleTimestamp; 48 | | uint256 maxOracleTimestamp; 49 | | Market.Props market; 50 | | address keeper; 51 | | uint256 startingGas; 52 | | Order.SecondaryOrderType secondaryOrderType; 53 | | } 54 | | 55 | | // @param dataStore DataStore 56 | | // @param eventEmitter EventEmitter 57 | | // @param orderVault OrderVault 58 | | // @param oracle Oracle 59 | | // @param swapHandler SwapHandler 60 | | // @param referralStorage IReferralStorage 61 | | struct ExecuteOrderParamsContracts { 62 | | DataStore dataStore; 63 | | EventEmitter eventEmitter; 64 | | OrderVault orderVault; 65 | | Oracle oracle; 66 | | SwapHandler swapHandler; 67 | | IReferralStorage referralStorage; 68 | | } 69 | | 70 | | struct GetExecutionPriceCache { 71 | | uint256 price; 72 | | uint256 executionPrice; 73 | | int256 adjustedPriceImpactUsd; 74 | | } 75 | | 76 | | // @dev check if an orderType is a market order 77 | | // @param orderType the order type 78 | | // @return whether an orderType is a market order 79 | * | function isMarketOrder(Order.OrderType orderType) internal pure returns (bool) { 80 | | // a liquidation order is not considered as a market order 81 | * | return orderType == Order.OrderType.MarketSwap || 82 | * | orderType == Order.OrderType.MarketIncrease || 83 | * | orderType == Order.OrderType.MarketDecrease; 84 | | } 85 | | 86 | | // @dev check if an orderType is a limit order 87 | | // @param orderType the order type 88 | | // @return whether an orderType is a limit order 89 | | function isLimitOrder(Order.OrderType orderType) internal pure returns (bool) { 90 | | return orderType == Order.OrderType.LimitSwap || 91 | | orderType == Order.OrderType.LimitIncrease || 92 | | orderType == Order.OrderType.LimitDecrease; 93 | | } 94 | | 95 | | // @dev check if an orderType is a swap order 96 | | // @param orderType the order type 97 | | // @return whether an orderType is a swap order 98 | * | function isSwapOrder(Order.OrderType orderType) internal pure returns (bool) { 99 | * | return orderType == Order.OrderType.MarketSwap || 100 | * | orderType == Order.OrderType.LimitSwap; 101 | | } 102 | | 103 | | // @dev check if an orderType is a position order 104 | | // @param orderType the order type 105 | | // @return whether an orderType is a position order 106 | * | function isPositionOrder(Order.OrderType orderType) internal pure returns (bool) { 107 | * | return isIncreaseOrder(orderType) || isDecreaseOrder(orderType); 108 | | } 109 | | 110 | | // @dev check if an orderType is an increase order 111 | | // @param orderType the order type 112 | | // @return whether an orderType is an increase order 113 | * | function isIncreaseOrder(Order.OrderType orderType) internal pure returns (bool) { 114 | * | return orderType == Order.OrderType.MarketIncrease || 115 | * | orderType == Order.OrderType.LimitIncrease; 116 | | } 117 | | 118 | | // @dev check if an orderType is a decrease order 119 | | // @param orderType the order type 120 | | // @return whether an orderType is a decrease order 121 | * | function isDecreaseOrder(Order.OrderType orderType) internal pure returns (bool) { 122 | * | return orderType == Order.OrderType.MarketDecrease || 123 | * | orderType == Order.OrderType.LimitDecrease || 124 | * | orderType == Order.OrderType.StopLossDecrease || 125 | * | orderType == Order.OrderType.Liquidation; 126 | | } 127 | | 128 | | // @dev check if an orderType is a liquidation order 129 | | // @param orderType the order type 130 | | // @return whether an orderType is a liquidation order 131 | * | function isLiquidationOrder(Order.OrderType orderType) internal pure returns (bool) { 132 | * | return orderType == Order.OrderType.Liquidation; 133 | | } 134 | | 135 | | // @dev validate the price for increase / decrease orders based on the triggerPrice 136 | | // the acceptablePrice for increase / decrease orders is validated in getExecutionPrice 137 | | // 138 | | // it is possible to update the oracle to support a primaryPrice and a secondaryPrice 139 | | // which would allow for stop-loss orders to be executed at exactly the triggerPrice 140 | | // 141 | | // however, this may lead to gaming issues, an example: 142 | | // - the current price is $2020 143 | | // - a user has a long position and creates a stop-loss decrease order for < $2010 144 | | // - if the order has a swap from ETH to USDC and the user is able to cause the order 145 | | // to be frozen / unexecutable by manipulating state or otherwise 146 | | // - then if price decreases to $2000, and the user is able to manipulate state such that 147 | | // the order becomes executable with $2010 being used as the price instead 148 | | // - then the user would be able to perform the swap at a higher price than should possible 149 | | // 150 | | // additionally, using the exact order's triggerPrice could lead to gaming issues during times 151 | | // of volatility due to users setting tight stop-losses to minimize loss while betting on a 152 | | // directional price movement, fees and price impact should help a bit with this, but there 153 | | // still may be some probability of success 154 | | // 155 | | // the order keepers can use the closest oracle price to the triggerPrice for execution, which 156 | | // should lead to similar order execution prices with reduced gaming risks 157 | | // 158 | | // if an order is frozen, the frozen order keepers should use the most recent price for order 159 | | // execution instead 160 | | // 161 | | // @param oracle Oracle 162 | | // @param indexToken the index token 163 | | // @param orderType the order type 164 | | // @param triggerPrice the order's triggerPrice 165 | | // @param isLong whether the order is for a long or short 166 | * | function validateOrderTriggerPrice( 167 | | Oracle oracle, 168 | | address indexToken, 169 | | Order.OrderType orderType, 170 | | uint256 triggerPrice, 171 | | bool isLong 172 | | ) internal view { 173 | * | if ( 174 | * | isSwapOrder(orderType) || 175 | * | isMarketOrder(orderType) || 176 | * | isLiquidationOrder(orderType) 177 | | ) { 178 | * | return; 179 | | } 180 | | 181 | * | Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken); 182 | | 183 | | // for limit increase long positions: 184 | | // - the order should be executed when the oracle price is <= triggerPrice 185 | | // - primaryPrice.max should be used for the oracle price 186 | | // for limit increase short positions: 187 | | // - the order should be executed when the oracle price is >= triggerPrice 188 | | // - primaryPrice.min should be used for the oracle price 189 | * | if (orderType == Order.OrderType.LimitIncrease) { 190 | * | bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice; 191 | | 192 | * | if (!ok) { 193 | * | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType)); 194 | | } 195 | | 196 | * | return; 197 | | } 198 | | 199 | | // for limit decrease long positions: 200 | | // - the order should be executed when the oracle price is >= triggerPrice 201 | | // - primaryPrice.min should be used for the oracle price 202 | | // for limit decrease short positions: 203 | | // - the order should be executed when the oracle price is <= triggerPrice 204 | | // - primaryPrice.max should be used for the oracle price 205 | * | if (orderType == Order.OrderType.LimitDecrease) { 206 | | bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice; 207 | | 208 | | if (!ok) { 209 | | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType)); 210 | | } 211 | | 212 | | return; 213 | | } 214 | | 215 | | // for stop-loss decrease long positions: 216 | | // - the order should be executed when the oracle price is <= triggerPrice 217 | | // - primaryPrice.min should be used for the oracle price 218 | | // for stop-loss decrease short positions: 219 | | // - the order should be executed when the oracle price is >= triggerPrice 220 | | // - primaryPrice.max should be used for the oracle price 221 | * | if (orderType == Order.OrderType.StopLossDecrease) { 222 | * | bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice; 223 | | 224 | * | if (!ok) { 225 | | revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType)); 226 | | } 227 | | 228 | * | return; 229 | | } 230 | | 231 | | revert Errors.UnsupportedOrderType(uint256(orderType)); 232 | | } 233 | | 234 | * | function getExecutionPriceForIncrease( 235 | | uint256 sizeDeltaUsd, 236 | | uint256 sizeDeltaInTokens, 237 | | uint256 acceptablePrice, 238 | | bool isLong 239 | * | ) internal pure returns (uint256) { 240 | * | if (sizeDeltaInTokens == 0) { 241 | * | revert Errors.EmptySizeDeltaInTokens(); 242 | | } 243 | | 244 | * | uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens; 245 | | 246 | | // increase order: 247 | | // - long: executionPrice should be smaller than acceptablePrice 248 | | // - short: executionPrice should be larger than acceptablePrice 249 | * | if ( 250 | * | (isLong && executionPrice <= acceptablePrice) || 251 | * | (!isLong && executionPrice >= acceptablePrice) 252 | | ) { 253 | * | return executionPrice; 254 | | } 255 | | 256 | | // the validateOrderTriggerPrice function should have validated if the price fulfills 257 | | // the order's trigger price 258 | | // 259 | | // for increase orders, the negative price impact is not capped 260 | | // 261 | | // for both increase and decrease orders, if it is due to price impact that the 262 | | // order cannot be fulfilled then the order should be frozen 263 | | // 264 | | // this is to prevent gaming by manipulation of the price impact value 265 | | // 266 | | // usually it should be costly to game the price impact value 267 | | // however, for certain cases, e.g. a user already has a large position opened 268 | | // the user may create limit orders that would only trigger after they close 269 | | // their position, this gives the user the option to cancel the pending order if 270 | | // prices do not move in their favour or to close their position and let the order 271 | | // execute if prices move in their favour 272 | | // 273 | | // it may also be possible for users to prevent the execution of orders from other users 274 | | // by manipulating the price impact, though this should be costly 275 | * | revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice); 276 | | } 277 | | 278 | * | function getExecutionPriceForDecrease( 279 | | Price.Props memory indexTokenPrice, 280 | | uint256 positionSizeInUsd, 281 | | uint256 positionSizeInTokens, 282 | | uint256 sizeDeltaUsd, 283 | | int256 priceImpactUsd, 284 | | uint256 acceptablePrice, 285 | | bool isLong 286 | * | ) internal pure returns (uint256) { 287 | * | GetExecutionPriceCache memory cache; 288 | | 289 | | // decrease order: 290 | | // - long: use the smaller price 291 | | // - short: use the larger price 292 | * | cache.price = indexTokenPrice.pickPrice(!isLong); 293 | * | cache.executionPrice = cache.price; 294 | | 295 | | // using closing of long positions as an example 296 | | // realized pnl is calculated as totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens 297 | | // totalPositionPnl: position.sizeInTokens * executionPrice - position.sizeInUsd 298 | | // sizeDeltaInTokens: position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd 299 | | // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (position.sizeInTokens * sizeDeltaUsd / position.sizeInUsd) / position.sizeInTokens 300 | | // realized pnl: (position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd) 301 | | // priceImpactUsd should adjust the execution price such that: 302 | | // [(position.sizeInTokens * executionPrice - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] - 303 | | // [(position.sizeInTokens * price - position.sizeInUsd) * (sizeDeltaUsd / position.sizeInUsd)] = priceImpactUsd 304 | | // 305 | | // (position.sizeInTokens * executionPrice - position.sizeInUsd) - (position.sizeInTokens * price - position.sizeInUsd) 306 | | // = priceImpactUsd / (sizeDeltaUsd / position.sizeInUsd) 307 | | // = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd 308 | | // 309 | | // position.sizeInTokens * executionPrice - position.sizeInTokens * price = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd 310 | | // position.sizeInTokens * (executionPrice - price) = priceImpactUsd * position.sizeInUsd / sizeDeltaUsd 311 | | // executionPrice - price = (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens) 312 | | // executionPrice = price + (priceImpactUsd * position.sizeInUsd) / (sizeDeltaUsd * position.sizeInTokens) 313 | | // executionPrice = price + (priceImpactUsd / sizeDeltaUsd) * (position.sizeInUsd / position.sizeInTokens) 314 | | // executionPrice = price + (priceImpactUsd * position.sizeInUsd / position.sizeInTokens) / sizeDeltaUsd 315 | | // 316 | | // e.g. if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000, position.sizeInUsd is $10,000, position.sizeInTokens is 5 317 | | // executionPrice = 2000 + (-1000 * 10,000 / 5) / 5000 = 1600 318 | | // realizedPnl based on price, without price impact: 0 319 | | // realizedPnl based on executionPrice, with price impact: (5 * 1600 - 10,000) * (5 * 5000 / 10,000) / 5 => -1000 320 | | 321 | | // a positive adjustedPriceImpactUsd would decrease the executionPrice 322 | | // a negative adjustedPriceImpactUsd would increase the executionPrice 323 | | 324 | | // for increase orders, the adjustedPriceImpactUsd is added to the divisor 325 | | // a positive adjustedPriceImpactUsd would increase the divisor and decrease the executionPrice 326 | | // increase long order: 327 | | // - if price impact is positive, adjustedPriceImpactUsd should be positive, to decrease the executionPrice 328 | | // - if price impact is negative, adjustedPriceImpactUsd should be negative, to increase the executionPrice 329 | | // increase short order: 330 | | // - if price impact is positive, adjustedPriceImpactUsd should be negative, to increase the executionPrice 331 | | // - if price impact is negative, adjustedPriceImpactUsd should be positive, to decrease the executionPrice 332 | | 333 | | // for decrease orders, the adjustedPriceImpactUsd adjusts the numerator 334 | | // a positive adjustedPriceImpactUsd would increase the divisor and increase the executionPrice 335 | | // decrease long order: 336 | | // - if price impact is positive, adjustedPriceImpactUsd should be positive, to increase the executionPrice 337 | | // - if price impact is negative, adjustedPriceImpactUsd should be negative, to decrease the executionPrice 338 | | // decrease short order: 339 | | // - if price impact is positive, adjustedPriceImpactUsd should be negative, to decrease the executionPrice 340 | | // - if price impact is negative, adjustedPriceImpactUsd should be positive, to increase the executionPrice 341 | | // adjust price by price impact 342 | * | if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) { 343 | * | cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd; 344 | | 345 | * | if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) { 346 | | revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd); 347 | | } 348 | | 349 | * | int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256(); 350 | * | int256 _executionPrice = cache.price.toInt256() + adjustment; 351 | | 352 | * | if (_executionPrice < 0) { 353 | | revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd); 354 | | } 355 | | 356 | * | cache.executionPrice = _executionPrice.toUint256(); 357 | | } 358 | | 359 | | // decrease order: 360 | | // - long: executionPrice should be larger than acceptablePrice 361 | | // - short: executionPrice should be smaller than acceptablePrice 362 | * | if ( 363 | * | (isLong && cache.executionPrice >= acceptablePrice) || 364 | * | (!isLong && cache.executionPrice <= acceptablePrice) 365 | | ) { 366 | * | return cache.executionPrice; 367 | | } 368 | | 369 | | // the validateOrderTriggerPrice function should have validated if the price fulfills 370 | | // the order's trigger price 371 | | // 372 | | // for decrease orders, the price impact should already be capped, so if the user 373 | | // had set an acceptable price within the range of the capped price impact, then 374 | | // the order should be fulfillable at the acceptable price 375 | | // 376 | | // for increase orders, the negative price impact is not capped 377 | | // 378 | | // for both increase and decrease orders, if it is due to price impact that the 379 | | // order cannot be fulfilled then the order should be frozen 380 | | // 381 | | // this is to prevent gaming by manipulation of the price impact value 382 | | // 383 | | // usually it should be costly to game the price impact value 384 | | // however, for certain cases, e.g. a user already has a large position opened 385 | | // the user may create limit orders that would only trigger after they close 386 | | // their position, this gives the user the option to cancel the pending order if 387 | | // prices do not move in their favour or to close their position and let the order 388 | | // execute if prices move in their favour 389 | | // 390 | | // it may also be possible for users to prevent the execution of orders from other users 391 | | // by manipulating the price impact, though this should be costly 392 | * | revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice); 393 | | } 394 | | 395 | | // @dev validate that an order exists 396 | | // @param order the order to check 397 | * | function validateNonEmptyOrder(Order.Props memory order) internal pure { 398 | * | if (order.account() == address(0)) { 399 | | revert Errors.EmptyOrder(); 400 | | } 401 | | 402 | * | if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) { 403 | * | revert Errors.EmptyOrder(); 404 | | } 405 | | } 406 | | 407 | * | function getPositionKey(Order.Props memory order) internal pure returns (bytes32) { 408 | * | if (isDecreaseOrder(order.orderType())) { 409 | * | return Position.getPositionKey( 410 | * | order.account(), 411 | * | order.market(), 412 | * | order.initialCollateralToken(), 413 | * | order.isLong() 414 | | ); 415 | | } 416 | | 417 | | revert Errors.UnsupportedOrderType(uint256(order.orderType())); 418 | | } 419 | | } 420 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/DecreaseOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderUtils.sol"; 6 | | import "../swap/SwapUtils.sol"; 7 | | import "../position/DecreasePositionUtils.sol"; 8 | | import "../order/OrderStoreUtils.sol"; 9 | | import "../error/ErrorUtils.sol"; 10 | | 11 | | // @title DecreaseOrderUtils 12 | | // @dev Library for functions to help with processing a decrease order 13 | | // note that any updates to the eventData 14 | * | library DecreaseOrderUtils { 15 | | using Position for Position.Props; 16 | | using Order for Order.Props; 17 | | using Array for uint256[]; 18 | | 19 | | using EventUtils for EventUtils.AddressItems; 20 | | using EventUtils for EventUtils.UintItems; 21 | | using EventUtils for EventUtils.IntItems; 22 | | using EventUtils for EventUtils.BoolItems; 23 | | using EventUtils for EventUtils.Bytes32Items; 24 | | using EventUtils for EventUtils.BytesItems; 25 | | using EventUtils for EventUtils.StringItems; 26 | | 27 | | // @dev process a decrease order 28 | | // @param params BaseOrderUtils.ExecuteOrderParams 29 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) { 30 | * | Order.Props memory order = params.order; 31 | * | MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market); 32 | | 33 | * | bytes32 positionKey = Position.getPositionKey(order.account(), order.market(), order.initialCollateralToken(), order.isLong()); 34 | * | Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey); 35 | * | PositionUtils.validateNonEmptyPosition(position); 36 | | 37 | * | validateOracleTimestamp( 38 | * | params.contracts.dataStore, 39 | * | order.orderType(), 40 | * | order.updatedAtTime(), 41 | * | position.increasedAtTime(), 42 | * | position.decreasedAtTime(), 43 | * | params.minOracleTimestamp, 44 | * | params.maxOracleTimestamp 45 | | ); 46 | | 47 | * | DecreasePositionUtils.DecreasePositionResult memory result = DecreasePositionUtils.decreasePosition( 48 | * | PositionUtils.UpdatePositionParams( 49 | * | params.contracts, 50 | * | params.market, 51 | * | order, 52 | * | params.key, 53 | * | position, 54 | * | positionKey, 55 | * | params.secondaryOrderType 56 | | ) 57 | | ); 58 | | 59 | | // if the pnlToken and the collateralToken are different 60 | | // and if a swap fails or no swap was requested 61 | | // then it is possible to receive two separate tokens from decreasing 62 | | // the position 63 | | // transfer the two tokens to the user in this case and skip processing 64 | | // the swapPath 65 | * | if (result.secondaryOutputAmount > 0) { 66 | * | _validateOutputAmount( 67 | * | params.contracts.oracle, 68 | * | result.outputToken, 69 | * | result.outputAmount, 70 | * | result.secondaryOutputToken, 71 | * | result.secondaryOutputAmount, 72 | * | order.minOutputAmount() 73 | | ); 74 | | 75 | * | MarketToken(payable(order.market())).transferOut( 76 | * | result.outputToken, 77 | * | order.receiver(), 78 | * | result.outputAmount, 79 | * | order.shouldUnwrapNativeToken() 80 | | ); 81 | | 82 | * | MarketToken(payable(order.market())).transferOut( 83 | * | result.secondaryOutputToken, 84 | * | order.receiver(), 85 | * | result.secondaryOutputAmount, 86 | * | order.shouldUnwrapNativeToken() 87 | | ); 88 | | 89 | * | return getOutputEventData( 90 | * | result.outputToken, 91 | * | result.outputAmount, 92 | * | result.secondaryOutputToken, 93 | * | result.secondaryOutputAmount, 94 | * | result.orderSizeDeltaUsd, 95 | * | result.orderInitialCollateralDeltaAmount 96 | | ); 97 | | } 98 | | 99 | * | try params.contracts.swapHandler.swap( 100 | * | SwapUtils.SwapParams( 101 | * | params.contracts.dataStore, 102 | * | params.contracts.eventEmitter, 103 | * | params.contracts.oracle, 104 | * | Bank(payable(order.market())), 105 | * | params.key, 106 | * | result.outputToken, 107 | * | result.outputAmount, 108 | * | params.swapPathMarkets, 109 | * | 0, 110 | * | order.receiver(), 111 | * | order.uiFeeReceiver(), 112 | * | order.shouldUnwrapNativeToken() 113 | | ) 114 | | ) returns (address tokenOut, uint256 swapOutputAmount) { 115 | * | _validateOutputAmount( 116 | * | params.contracts.oracle, 117 | * | tokenOut, 118 | * | swapOutputAmount, 119 | * | order.minOutputAmount() 120 | | ); 121 | | 122 | * | return getOutputEventData( 123 | * | tokenOut, 124 | * | swapOutputAmount, 125 | * | address(0), 126 | * | 0, 127 | * | result.orderSizeDeltaUsd, 128 | * | result.orderInitialCollateralDeltaAmount 129 | | ); 130 | | } catch (bytes memory reasonBytes) { 131 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 132 | | 133 | | _handleSwapError( 134 | | params.contracts.oracle, 135 | | order, 136 | | result, 137 | | reason, 138 | | reasonBytes 139 | | ); 140 | | 141 | | return getOutputEventData( 142 | | result.outputToken, 143 | | result.outputAmount, 144 | | address(0), 145 | | 0, 146 | | result.orderSizeDeltaUsd, 147 | | result.orderInitialCollateralDeltaAmount 148 | | ); 149 | | } 150 | | } 151 | | 152 | * | function validateOracleTimestamp( 153 | | DataStore dataStore, 154 | | Order.OrderType orderType, 155 | | uint256 orderUpdatedAtTime, 156 | | uint256 positionIncreasedAtTime, 157 | | uint256 positionDecreasedAtTime, 158 | | uint256 minOracleTimestamp, 159 | | uint256 maxOracleTimestamp 160 | | ) internal view { 161 | * | if (orderType == Order.OrderType.MarketDecrease) { 162 | * | if (minOracleTimestamp < orderUpdatedAtTime) { 163 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, orderUpdatedAtTime); 164 | | } 165 | | 166 | * | uint256 requestExpirationTime = dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 167 | | 168 | * | if (maxOracleTimestamp > orderUpdatedAtTime + requestExpirationTime) { 169 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 170 | * | maxOracleTimestamp, 171 | * | orderUpdatedAtTime, 172 | * | requestExpirationTime 173 | | ); 174 | | } 175 | * | return; 176 | | } 177 | | 178 | | // a user could attempt to frontrun prices by creating a limit decrease 179 | | // order without a position 180 | | // when price moves in the user's favour, the user would create a 181 | | // position then 182 | | // e.g. price is $5000, a user creates a stop-loss order to 183 | | // close a long position when price is below $5000 184 | | // if price decreases to $4995, the user opens a long position at 185 | | // price $4995 186 | | // since slightly older prices may be used to execute a position 187 | | // the user's stop-loss order could be executed at price $5000 188 | | // for this reason, both the orderUpdatedAtTime and the 189 | | // positionIncreasedAtTime need to be used as a reference 190 | | // 191 | | // if there are multiple decrease orders, an execution of one decrease 192 | | // order would update the position, so the reference check here is only 193 | | // with positionIncreasedAtTime instead of a positionUpdatedAtTime value 194 | * | if ( 195 | * | orderType == Order.OrderType.LimitDecrease || 196 | * | orderType == Order.OrderType.StopLossDecrease 197 | | ) { 198 | * | uint256 latestUpdatedAtTime = orderUpdatedAtTime > positionIncreasedAtTime ? orderUpdatedAtTime : positionIncreasedAtTime; 199 | * | if (minOracleTimestamp < latestUpdatedAtTime) { 200 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime); 201 | | } 202 | * | return; 203 | | } 204 | | 205 | * | if (orderType == Order.OrderType.Liquidation) { 206 | * | uint256 latestUpdatedAtTime = positionIncreasedAtTime > positionDecreasedAtTime ? positionIncreasedAtTime : positionDecreasedAtTime; 207 | * | if (minOracleTimestamp < latestUpdatedAtTime) { 208 | | revert Errors.OracleTimestampsAreSmallerThanRequired(minOracleTimestamp, latestUpdatedAtTime); 209 | | } 210 | * | return; 211 | | } 212 | | 213 | | revert Errors.UnsupportedOrderType(uint256(orderType)); 214 | | } 215 | | 216 | | // note that minOutputAmount is treated as a USD value for this validation 217 | * | function _validateOutputAmount( 218 | | Oracle oracle, 219 | | address outputToken, 220 | | uint256 outputAmount, 221 | | uint256 minOutputAmount 222 | * | ) internal view { 223 | * | uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min; 224 | * | uint256 outputUsd = outputAmount * outputTokenPrice; 225 | | 226 | * | if (outputUsd < minOutputAmount) { 227 | | revert Errors.InsufficientOutputAmount(outputUsd, minOutputAmount); 228 | | } 229 | | } 230 | | 231 | | // note that minOutputAmount is treated as a USD value for this validation 232 | * | function _validateOutputAmount( 233 | | Oracle oracle, 234 | | address outputToken, 235 | | uint256 outputAmount, 236 | | address secondaryOutputToken, 237 | | uint256 secondaryOutputAmount, 238 | | uint256 minOutputAmount 239 | * | ) internal view { 240 | * | uint256 outputTokenPrice = oracle.getPrimaryPrice(outputToken).min; 241 | * | uint256 outputUsd = outputAmount * outputTokenPrice; 242 | | 243 | * | uint256 secondaryOutputTokenPrice = oracle.getPrimaryPrice(secondaryOutputToken).min; 244 | * | uint256 secondaryOutputUsd = secondaryOutputAmount * secondaryOutputTokenPrice; 245 | | 246 | * | uint256 totalOutputUsd = outputUsd + secondaryOutputUsd; 247 | | 248 | * | if (totalOutputUsd < minOutputAmount) { 249 | | revert Errors.InsufficientOutputAmount(totalOutputUsd, minOutputAmount); 250 | | } 251 | | } 252 | | 253 | | function _handleSwapError( 254 | | Oracle oracle, 255 | | Order.Props memory order, 256 | | DecreasePositionUtils.DecreasePositionResult memory result, 257 | | string memory reason, 258 | | bytes memory reasonBytes 259 | | ) internal { 260 | | emit SwapUtils.SwapReverted(reason, reasonBytes); 261 | | 262 | | _validateOutputAmount( 263 | | oracle, 264 | | result.outputToken, 265 | | result.outputAmount, 266 | | order.minOutputAmount() 267 | | ); 268 | | 269 | | MarketToken(payable(order.market())).transferOut( 270 | | result.outputToken, 271 | | order.receiver(), 272 | | result.outputAmount, 273 | | order.shouldUnwrapNativeToken() 274 | | ); 275 | | } 276 | | 277 | * | function getOutputEventData( 278 | | address outputToken, 279 | | uint256 outputAmount, 280 | | address secondaryOutputToken, 281 | | uint256 secondaryOutputAmount, 282 | | uint256 orderSizeDeltaUsd, 283 | | uint256 orderInitialCollateralDeltaAmount 284 | * | ) internal pure returns (EventUtils.EventLogData memory) { 285 | * | EventUtils.EventLogData memory eventData; 286 | * | eventData.addressItems.initItems(2); 287 | * | eventData.addressItems.setItem(0, "outputToken", outputToken); 288 | * | eventData.addressItems.setItem(1, "secondaryOutputToken", secondaryOutputToken); 289 | | 290 | * | eventData.uintItems.initItems(4); 291 | * | eventData.uintItems.setItem(0, "outputAmount", outputAmount); 292 | * | eventData.uintItems.setItem(1, "secondaryOutputAmount", secondaryOutputAmount); 293 | * | eventData.uintItems.setItem(2, "orderSizeDeltaUsd", orderSizeDeltaUsd); 294 | * | eventData.uintItems.setItem(3, "orderInitialCollateralDeltaAmount", orderInitialCollateralDeltaAmount); 295 | | 296 | * | return eventData; 297 | | } 298 | | } 299 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/ExecuteOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./AutoCancelUtils.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "./Order.sol"; 10 | | import "./OrderVault.sol"; 11 | | import "./OrderStoreUtils.sol"; 12 | | import "./OrderEventUtils.sol"; 13 | | import "./OrderUtils.sol"; 14 | | 15 | | import "../nonce/NonceUtils.sol"; 16 | | import "../oracle/Oracle.sol"; 17 | | import "../oracle/OracleUtils.sol"; 18 | | import "../event/EventEmitter.sol"; 19 | | 20 | | import "./IncreaseOrderUtils.sol"; 21 | | import "./DecreaseOrderUtils.sol"; 22 | | import "./SwapOrderUtils.sol"; 23 | | import "./BaseOrderUtils.sol"; 24 | | 25 | | import "../swap/SwapUtils.sol"; 26 | | 27 | | import "../gas/GasUtils.sol"; 28 | | import "../callback/CallbackUtils.sol"; 29 | | 30 | | import "../utils/Array.sol"; 31 | | import "../utils/AccountUtils.sol"; 32 | | import "../referral/ReferralUtils.sol"; 33 | | 34 | * | library ExecuteOrderUtils { 35 | | using Order for Order.Props; 36 | | using Position for Position.Props; 37 | | using Price for Price.Props; 38 | | using Array for uint256[]; 39 | | 40 | | // @dev executes an order 41 | | // @param params BaseOrderUtils.ExecuteOrderParams 42 | * | function executeOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal { 43 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 44 | * | params.startingGas -= gasleft() / 63; 45 | | 46 | * | OrderStoreUtils.remove(params.contracts.dataStore, params.key, params.order.account()); 47 | | 48 | * | BaseOrderUtils.validateNonEmptyOrder(params.order); 49 | | 50 | * | BaseOrderUtils.validateOrderTriggerPrice( 51 | * | params.contracts.oracle, 52 | * | params.market.indexToken, 53 | * | params.order.orderType(), 54 | * | params.order.triggerPrice(), 55 | * | params.order.isLong() 56 | | ); 57 | | 58 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices( 59 | * | params.contracts.oracle, 60 | * | params.market 61 | | ); 62 | | 63 | * | MarketUtils.distributePositionImpactPool( 64 | * | params.contracts.dataStore, 65 | * | params.contracts.eventEmitter, 66 | * | params.market.marketToken 67 | | ); 68 | | 69 | * | PositionUtils.updateFundingAndBorrowingState( 70 | * | params.contracts.dataStore, 71 | * | params.contracts.eventEmitter, 72 | * | params.market, 73 | * | prices 74 | | ); 75 | | 76 | * | EventUtils.EventLogData memory eventData = processOrder(params); 77 | | 78 | | // validate that internal state changes are correct before calling 79 | | // internal callbacks 80 | | // if the native token was transferred to the receiver in a swap 81 | | // it may be possible to invoke internal contracts before the validations 82 | | // are called 83 | * | if (params.market.marketToken != address(0)) { 84 | * | MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.market); 85 | | } 86 | * | MarketUtils.validateMarketTokenBalance(params.contracts.dataStore, params.swapPathMarkets); 87 | | 88 | * | OrderUtils.updateAutoCancelList(params.contracts.dataStore, params.key, params.order, false); 89 | | 90 | * | OrderEventUtils.emitOrderExecuted( 91 | * | params.contracts.eventEmitter, 92 | * | params.key, 93 | * | params.order.account(), 94 | * | params.secondaryOrderType 95 | | ); 96 | | 97 | * | CallbackUtils.afterOrderExecution(params.key, params.order, eventData); 98 | | 99 | | // the order.executionFee for liquidation / adl orders is zero 100 | | // gas costs for liquidations / adl is subsidised by the treasury 101 | * | GasUtils.payExecutionFee( 102 | * | params.contracts.dataStore, 103 | * | params.contracts.eventEmitter, 104 | * | params.contracts.orderVault, 105 | * | params.key, 106 | * | params.order.callbackContract(), 107 | * | params.order.executionFee(), 108 | * | params.startingGas, 109 | * | GasUtils.estimateOrderOraclePriceCount(params.order.swapPath().length), 110 | * | params.keeper, 111 | * | params.order.receiver() 112 | | ); 113 | | 114 | | // clearAutoCancelOrders should be called after the main execution fee 115 | | // is called 116 | | // this is because clearAutoCancelOrders loops through each order for 117 | | // the associated position and calls cancelOrder, which pays the keeper 118 | | // based on the gas usage for each cancel order 119 | * | if (BaseOrderUtils.isDecreaseOrder(params.order.orderType())) { 120 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(params.order); 121 | * | uint256 sizeInUsd = params.contracts.dataStore.getUint( 122 | * | keccak256(abi.encode(positionKey, PositionStoreUtils.SIZE_IN_USD)) 123 | | ); 124 | * | if (sizeInUsd == 0) { 125 | * | OrderUtils.clearAutoCancelOrders( 126 | * | params.contracts.dataStore, 127 | * | params.contracts.eventEmitter, 128 | * | params.contracts.orderVault, 129 | * | positionKey, 130 | * | params.keeper 131 | | ); 132 | | } 133 | | } 134 | | } 135 | | 136 | | // @dev process an order execution 137 | | // @param params BaseOrderUtils.ExecuteOrderParams 138 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) { 139 | * | if (BaseOrderUtils.isIncreaseOrder(params.order.orderType())) { 140 | * | return IncreaseOrderUtils.processOrder(params); 141 | | } 142 | | 143 | * | if (BaseOrderUtils.isDecreaseOrder(params.order.orderType())) { 144 | * | return DecreaseOrderUtils.processOrder(params); 145 | | } 146 | | 147 | * | if (BaseOrderUtils.isSwapOrder(params.order.orderType())) { 148 | * | return SwapOrderUtils.processOrder(params); 149 | | } 150 | | 151 | | revert Errors.UnsupportedOrderType(uint256(params.order.orderType())); 152 | | } 153 | | } 154 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/IBaseOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./Order.sol"; 6 | | 7 | | interface IBaseOrderUtils { 8 | | // @dev CreateOrderParams struct used in createOrder to avoid stack 9 | | // too deep errors 10 | | // 11 | | // @param addresses address values 12 | | // @param numbers number values 13 | | // @param orderType for order.orderType 14 | | // @param decreasePositionSwapType for order.decreasePositionSwapType 15 | | // @param isLong for order.isLong 16 | | // @param shouldUnwrapNativeToken for order.shouldUnwrapNativeToken 17 | | struct CreateOrderParams { 18 | | CreateOrderParamsAddresses addresses; 19 | | CreateOrderParamsNumbers numbers; 20 | | Order.OrderType orderType; 21 | | Order.DecreasePositionSwapType decreasePositionSwapType; 22 | | bool isLong; 23 | | bool shouldUnwrapNativeToken; 24 | | bool autoCancel; 25 | | bytes32 referralCode; 26 | | } 27 | | 28 | | struct CreateOrderParamsAddresses { 29 | | address receiver; 30 | | address cancellationReceiver; 31 | | address callbackContract; 32 | | address uiFeeReceiver; 33 | | address market; 34 | | address initialCollateralToken; 35 | | address[] swapPath; 36 | | } 37 | | 38 | | // @param sizeDeltaUsd for order.sizeDeltaUsd 39 | | // @param triggerPrice for order.triggerPrice 40 | | // @param acceptablePrice for order.acceptablePrice 41 | | // @param executionFee for order.executionFee 42 | | // @param callbackGasLimit for order.callbackGasLimit 43 | | // @param minOutputAmount for order.minOutputAmount 44 | | struct CreateOrderParamsNumbers { 45 | | uint256 sizeDeltaUsd; 46 | | uint256 initialCollateralDeltaAmount; 47 | | uint256 triggerPrice; 48 | | uint256 acceptablePrice; 49 | | uint256 executionFee; 50 | | uint256 callbackGasLimit; 51 | | uint256 minOutputAmount; 52 | | } 53 | | } 54 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/IncreaseOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderUtils.sol"; 6 | | import "../swap/SwapUtils.sol"; 7 | | import "../position/IncreasePositionUtils.sol"; 8 | | import "../order/OrderStoreUtils.sol"; 9 | | import "../callback/CallbackUtils.sol"; 10 | | 11 | | // @title IncreaseOrderUtils 12 | | // @dev Library for functions to help with processing an increase order 13 | * | library IncreaseOrderUtils { 14 | | using Position for Position.Props; 15 | | using Order for Order.Props; 16 | | using Array for uint256[]; 17 | | 18 | | // @dev process an increase order 19 | | // @param params BaseOrderUtils.ExecuteOrderParams 20 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) { 21 | * | MarketUtils.validatePositionMarket(params.contracts.dataStore, params.market); 22 | | 23 | * | (address collateralToken, uint256 collateralIncrementAmount) = SwapUtils.swap(SwapUtils.SwapParams( 24 | * | params.contracts.dataStore, 25 | * | params.contracts.eventEmitter, 26 | * | params.contracts.oracle, 27 | * | params.contracts.orderVault, 28 | * | params.key, 29 | * | params.order.initialCollateralToken(), 30 | * | params.order.initialCollateralDeltaAmount(), 31 | * | params.swapPathMarkets, 32 | * | params.order.minOutputAmount(), 33 | * | params.order.market(), 34 | * | params.order.uiFeeReceiver(), 35 | * | false 36 | | )); 37 | | 38 | * | MarketUtils.validateMarketCollateralToken(params.market, collateralToken); 39 | | 40 | * | bytes32 positionKey = Position.getPositionKey(params.order.account(), params.order.market(), collateralToken, params.order.isLong()); 41 | * | Position.Props memory position = PositionStoreUtils.get(params.contracts.dataStore, positionKey); 42 | | 43 | | // initialize position 44 | * | if (position.account() == address(0)) { 45 | * | position.setAccount(params.order.account()); 46 | * | if (position.market() != address(0) || position.collateralToken() != address(0)) { 47 | | revert Errors.UnexpectedPositionState(); 48 | | } 49 | | 50 | * | position.setMarket(params.order.market()); 51 | * | position.setCollateralToken(collateralToken); 52 | * | position.setIsLong(params.order.isLong()); 53 | | } 54 | | 55 | * | uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 56 | | 57 | * | if (params.minOracleTimestamp < params.order.updatedAtTime()) { 58 | | revert Errors.OracleTimestampsAreSmallerThanRequired( 59 | | params.minOracleTimestamp, 60 | | params.order.updatedAtTime() 61 | | ); 62 | | } 63 | | 64 | * | if ( 65 | * | params.order.orderType() == Order.OrderType.MarketIncrease && 66 | * | params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime 67 | | ) { 68 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 69 | * | params.maxOracleTimestamp, 70 | * | params.order.updatedAtTime(), 71 | * | requestExpirationTime 72 | | ); 73 | | } 74 | | 75 | * | IncreasePositionUtils.increasePosition( 76 | * | PositionUtils.UpdatePositionParams( 77 | * | params.contracts, 78 | * | params.market, 79 | * | params.order, 80 | * | params.key, 81 | * | position, 82 | * | positionKey, 83 | * | params.secondaryOrderType 84 | | ), 85 | * | collateralIncrementAmount 86 | | ); 87 | | 88 | * | EventUtils.EventLogData memory eventData; 89 | * | return eventData; 90 | | } 91 | | } 92 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/Order.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../chain/Chain.sol"; 6 | | 7 | | // @title Order 8 | | // @dev Struct for orders 9 | * | library Order { 10 | | using Order for Props; 11 | | 12 | | enum OrderType { 13 | | // @dev MarketSwap: swap token A to token B at the current market price 14 | | // the order will be cancelled if the minOutputAmount cannot be fulfilled 15 | | MarketSwap, 16 | | // @dev LimitSwap: swap token A to token B if the minOutputAmount can be fulfilled 17 | | LimitSwap, 18 | | // @dev MarketIncrease: increase position at the current market price 19 | | // the order will be cancelled if the position cannot be increased at the acceptablePrice 20 | | MarketIncrease, 21 | | // @dev LimitIncrease: increase position if the triggerPrice is reached and the acceptablePrice can be fulfilled 22 | | LimitIncrease, 23 | | // @dev MarketDecrease: decrease position at the current market price 24 | | // the order will be cancelled if the position cannot be decreased at the acceptablePrice 25 | | MarketDecrease, 26 | | // @dev LimitDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled 27 | | LimitDecrease, 28 | | // @dev StopLossDecrease: decrease position if the triggerPrice is reached and the acceptablePrice can be fulfilled 29 | | StopLossDecrease, 30 | | // @dev Liquidation: allows liquidation of positions if the criteria for liquidation are met 31 | | Liquidation 32 | | } 33 | | 34 | | // to help further differentiate orders 35 | | enum SecondaryOrderType { 36 | | None, 37 | | Adl 38 | | } 39 | | 40 | | enum DecreasePositionSwapType { 41 | | NoSwap, 42 | | SwapPnlTokenToCollateralToken, 43 | | SwapCollateralTokenToPnlToken 44 | | } 45 | | 46 | | // @dev there is a limit on the number of fields a struct can have when being passed 47 | | // or returned as a memory variable which can cause "Stack too deep" errors 48 | | // use sub-structs to avoid this issue 49 | | // @param addresses address values 50 | | // @param numbers number values 51 | | // @param flags boolean values 52 | | struct Props { 53 | | Addresses addresses; 54 | | Numbers numbers; 55 | | Flags flags; 56 | | } 57 | | 58 | | // @param account the account of the order 59 | | // @param receiver the receiver for any token transfers 60 | | // this field is meant to allow the output of an order to be 61 | | // received by an address that is different from the creator of the 62 | | // order whether this is for swaps or whether the account is the owner 63 | | // of a position 64 | | // for funding fees and claimable collateral, the funds are still 65 | | // credited to the owner of the position indicated by order.account 66 | | // @param callbackContract the contract to call for callbacks 67 | | // @param uiFeeReceiver the ui fee receiver 68 | | // @param market the trading market 69 | | // @param initialCollateralToken for increase orders, initialCollateralToken 70 | | // is the token sent in by the user, the token will be swapped through the 71 | | // specified swapPath, before being deposited into the position as collateral 72 | | // for decrease orders, initialCollateralToken is the collateral token of the position 73 | | // withdrawn collateral from the decrease of the position will be swapped 74 | | // through the specified swapPath 75 | | // for swaps, initialCollateralToken is the initial token sent for the swap 76 | | // @param swapPath an array of market addresses to swap through 77 | | struct Addresses { 78 | | address account; 79 | | address receiver; 80 | | address cancellationReceiver; 81 | | address callbackContract; 82 | | address uiFeeReceiver; 83 | | address market; 84 | | address initialCollateralToken; 85 | | address[] swapPath; 86 | | } 87 | | 88 | | // @param sizeDeltaUsd the requested change in position size 89 | | // @param initialCollateralDeltaAmount for increase orders, initialCollateralDeltaAmount 90 | | // is the amount of the initialCollateralToken sent in by the user 91 | | // for decrease orders, initialCollateralDeltaAmount is the amount of the position's 92 | | // collateralToken to withdraw 93 | | // for swaps, initialCollateralDeltaAmount is the amount of initialCollateralToken sent 94 | | // in for the swap 95 | | // @param orderType the order type 96 | | // @param triggerPrice the trigger price for non-market orders 97 | | // @param acceptablePrice the acceptable execution price for increase / decrease orders 98 | | // @param executionFee the execution fee for keepers 99 | | // @param callbackGasLimit the gas limit for the callbackContract 100 | | // @param minOutputAmount the minimum output amount for decrease orders and swaps 101 | | // note that for decrease orders, multiple tokens could be received, for this reason, the 102 | | // minOutputAmount value is treated as a USD value for validation in decrease orders 103 | | // @param updatedAtBlock the block at which the order was last updated 104 | | struct Numbers { 105 | | OrderType orderType; 106 | | DecreasePositionSwapType decreasePositionSwapType; 107 | | uint256 sizeDeltaUsd; 108 | | uint256 initialCollateralDeltaAmount; 109 | | uint256 triggerPrice; 110 | | uint256 acceptablePrice; 111 | | uint256 executionFee; 112 | | uint256 callbackGasLimit; 113 | | uint256 minOutputAmount; 114 | | uint256 updatedAtBlock; 115 | | uint256 updatedAtTime; 116 | | } 117 | | 118 | | // @param isLong whether the order is for a long or short 119 | | // @param shouldUnwrapNativeToken whether to unwrap native tokens before 120 | | // transferring to the user 121 | | // @param isFrozen whether the order is frozen 122 | | struct Flags { 123 | | bool isLong; 124 | | bool shouldUnwrapNativeToken; 125 | | bool isFrozen; 126 | | bool autoCancel; 127 | | } 128 | | 129 | | // @dev the order account 130 | | // @param props Props 131 | | // @return the order account 132 | * | function account(Props memory props) internal pure returns (address) { 133 | * | return props.addresses.account; 134 | | } 135 | | 136 | | // @dev set the order account 137 | | // @param props Props 138 | | // @param value the value to set to 139 | * | function setAccount(Props memory props, address value) internal pure { 140 | * | props.addresses.account = value; 141 | | } 142 | | 143 | | // @dev the order receiver 144 | | // @param props Props 145 | | // @return the order receiver 146 | * | function receiver(Props memory props) internal pure returns (address) { 147 | * | return props.addresses.receiver; 148 | | } 149 | | 150 | | // @dev set the order receiver 151 | | // @param props Props 152 | | // @param value the value to set to 153 | * | function setReceiver(Props memory props, address value) internal pure { 154 | * | props.addresses.receiver = value; 155 | | } 156 | | 157 | * | function cancellationReceiver(Props memory props) internal pure returns (address) { 158 | * | return props.addresses.cancellationReceiver; 159 | | } 160 | | 161 | * | function setCancellationReceiver(Props memory props, address value) internal pure { 162 | * | props.addresses.cancellationReceiver = value; 163 | | } 164 | | 165 | | // @dev the order callbackContract 166 | | // @param props Props 167 | | // @return the order callbackContract 168 | * | function callbackContract(Props memory props) internal pure returns (address) { 169 | * | return props.addresses.callbackContract; 170 | | } 171 | | 172 | | // @dev set the order callbackContract 173 | | // @param props Props 174 | | // @param value the value to set to 175 | * | function setCallbackContract(Props memory props, address value) internal pure { 176 | * | props.addresses.callbackContract = value; 177 | | } 178 | | 179 | | // @dev the order market 180 | | // @param props Props 181 | | // @return the order market 182 | * | function market(Props memory props) internal pure returns (address) { 183 | * | return props.addresses.market; 184 | | } 185 | | 186 | | // @dev set the order market 187 | | // @param props Props 188 | | // @param value the value to set to 189 | * | function setMarket(Props memory props, address value) internal pure { 190 | * | props.addresses.market = value; 191 | | } 192 | | 193 | | // @dev the order initialCollateralToken 194 | | // @param props Props 195 | | // @return the order initialCollateralToken 196 | * | function initialCollateralToken(Props memory props) internal pure returns (address) { 197 | * | return props.addresses.initialCollateralToken; 198 | | } 199 | | 200 | | // @dev set the order initialCollateralToken 201 | | // @param props Props 202 | | // @param value the value to set to 203 | * | function setInitialCollateralToken(Props memory props, address value) internal pure { 204 | * | props.addresses.initialCollateralToken = value; 205 | | } 206 | | 207 | | // @dev the order uiFeeReceiver 208 | | // @param props Props 209 | | // @return the order uiFeeReceiver 210 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) { 211 | * | return props.addresses.uiFeeReceiver; 212 | | } 213 | | 214 | | // @dev set the order uiFeeReceiver 215 | | // @param props Props 216 | | // @param value the value to set to 217 | * | function setUiFeeReceiver(Props memory props, address value) internal pure { 218 | * | props.addresses.uiFeeReceiver = value; 219 | | } 220 | | 221 | | // @dev the order swapPath 222 | | // @param props Props 223 | | // @return the order swapPath 224 | * | function swapPath(Props memory props) internal pure returns (address[] memory) { 225 | * | return props.addresses.swapPath; 226 | | } 227 | | 228 | | // @dev set the order swapPath 229 | | // @param props Props 230 | | // @param value the value to set to 231 | * | function setSwapPath(Props memory props, address[] memory value) internal pure { 232 | * | props.addresses.swapPath = value; 233 | | } 234 | | 235 | | // @dev the order type 236 | | // @param props Props 237 | | // @return the order type 238 | * | function orderType(Props memory props) internal pure returns (OrderType) { 239 | * | return props.numbers.orderType; 240 | | } 241 | | 242 | | // @dev set the order type 243 | | // @param props Props 244 | | // @param value the value to set to 245 | * | function setOrderType(Props memory props, OrderType value) internal pure { 246 | * | props.numbers.orderType = value; 247 | | } 248 | | 249 | * | function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) { 250 | * | return props.numbers.decreasePositionSwapType; 251 | | } 252 | | 253 | * | function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure { 254 | * | props.numbers.decreasePositionSwapType = value; 255 | | } 256 | | 257 | | // @dev the order sizeDeltaUsd 258 | | // @param props Props 259 | | // @return the order sizeDeltaUsd 260 | * | function sizeDeltaUsd(Props memory props) internal pure returns (uint256) { 261 | * | return props.numbers.sizeDeltaUsd; 262 | | } 263 | | 264 | | // @dev set the order sizeDeltaUsd 265 | | // @param props Props 266 | | // @param value the value to set to 267 | * | function setSizeDeltaUsd(Props memory props, uint256 value) internal pure { 268 | * | props.numbers.sizeDeltaUsd = value; 269 | | } 270 | | 271 | | // @dev the order initialCollateralDeltaAmount 272 | | // @param props Props 273 | | // @return the order initialCollateralDeltaAmount 274 | * | function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) { 275 | * | return props.numbers.initialCollateralDeltaAmount; 276 | | } 277 | | 278 | | // @dev set the order initialCollateralDeltaAmount 279 | | // @param props Props 280 | | // @param value the value to set to 281 | * | function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure { 282 | * | props.numbers.initialCollateralDeltaAmount = value; 283 | | } 284 | | 285 | | // @dev the order triggerPrice 286 | | // @param props Props 287 | | // @return the order triggerPrice 288 | * | function triggerPrice(Props memory props) internal pure returns (uint256) { 289 | * | return props.numbers.triggerPrice; 290 | | } 291 | | 292 | | // @dev set the order triggerPrice 293 | | // @param props Props 294 | | // @param value the value to set to 295 | * | function setTriggerPrice(Props memory props, uint256 value) internal pure { 296 | * | props.numbers.triggerPrice = value; 297 | | } 298 | | 299 | | // @dev the order acceptablePrice 300 | | // @param props Props 301 | | // @return the order acceptablePrice 302 | * | function acceptablePrice(Props memory props) internal pure returns (uint256) { 303 | * | return props.numbers.acceptablePrice; 304 | | } 305 | | 306 | | // @dev set the order acceptablePrice 307 | | // @param props Props 308 | | // @param value the value to set to 309 | * | function setAcceptablePrice(Props memory props, uint256 value) internal pure { 310 | * | props.numbers.acceptablePrice = value; 311 | | } 312 | | 313 | | // @dev set the order executionFee 314 | | // @param props Props 315 | | // @param value the value to set to 316 | * | function setExecutionFee(Props memory props, uint256 value) internal pure { 317 | * | props.numbers.executionFee = value; 318 | | } 319 | | 320 | | // @dev the order executionFee 321 | | // @param props Props 322 | | // @return the order executionFee 323 | * | function executionFee(Props memory props) internal pure returns (uint256) { 324 | * | return props.numbers.executionFee; 325 | | } 326 | | 327 | | // @dev the order callbackGasLimit 328 | | // @param props Props 329 | | // @return the order callbackGasLimit 330 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) { 331 | * | return props.numbers.callbackGasLimit; 332 | | } 333 | | 334 | | // @dev set the order callbackGasLimit 335 | | // @param props Props 336 | | // @param value the value to set to 337 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure { 338 | * | props.numbers.callbackGasLimit = value; 339 | | } 340 | | 341 | | // @dev the order minOutputAmount 342 | | // @param props Props 343 | | // @return the order minOutputAmount 344 | * | function minOutputAmount(Props memory props) internal pure returns (uint256) { 345 | * | return props.numbers.minOutputAmount; 346 | | } 347 | | 348 | | // @dev set the order minOutputAmount 349 | | // @param props Props 350 | | // @param value the value to set to 351 | * | function setMinOutputAmount(Props memory props, uint256 value) internal pure { 352 | * | props.numbers.minOutputAmount = value; 353 | | } 354 | | 355 | | // @dev the order updatedAtBlock 356 | | // @param props Props 357 | | // @return the order updatedAtBlock 358 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) { 359 | * | return props.numbers.updatedAtBlock; 360 | | } 361 | | 362 | | // @dev set the order updatedAtBlock 363 | | // @param props Props 364 | | // @param value the value to set to 365 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure { 366 | * | props.numbers.updatedAtBlock = value; 367 | | } 368 | | 369 | | // @dev the order updatedAtTime 370 | | // @param props Props 371 | | // @return the order updatedAtTime 372 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) { 373 | * | return props.numbers.updatedAtTime; 374 | | } 375 | | 376 | | // @dev set the order updatedAtTime 377 | | // @param props Props 378 | | // @param value the value to set to 379 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure { 380 | * | props.numbers.updatedAtTime = value; 381 | | } 382 | | 383 | | // @dev whether the order is for a long or short 384 | | // @param props Props 385 | | // @return whether the order is for a long or short 386 | * | function isLong(Props memory props) internal pure returns (bool) { 387 | * | return props.flags.isLong; 388 | | } 389 | | 390 | | // @dev set whether the order is for a long or short 391 | | // @param props Props 392 | | // @param value the value to set to 393 | * | function setIsLong(Props memory props, bool value) internal pure { 394 | * | props.flags.isLong = value; 395 | | } 396 | | 397 | | // @dev whether to unwrap the native token before transfers to the user 398 | | // @param props Props 399 | | // @return whether to unwrap the native token before transfers to the user 400 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) { 401 | * | return props.flags.shouldUnwrapNativeToken; 402 | | } 403 | | 404 | | // @dev set whether the native token should be unwrapped before being 405 | | // transferred to the receiver 406 | | // @param props Props 407 | | // @param value the value to set to 408 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure { 409 | * | props.flags.shouldUnwrapNativeToken = value; 410 | | } 411 | | 412 | | // @dev whether the order is frozen 413 | | // @param props Props 414 | | // @return whether the order is frozen 415 | * | function isFrozen(Props memory props) internal pure returns (bool) { 416 | * | return props.flags.isFrozen; 417 | | } 418 | | 419 | | // @dev set whether the order is frozen 420 | | // transferred to the receiver 421 | | // @param props Props 422 | | // @param value the value to set to 423 | * | function setIsFrozen(Props memory props, bool value) internal pure { 424 | * | props.flags.isFrozen = value; 425 | | } 426 | | 427 | * | function autoCancel(Props memory props) internal pure returns (bool) { 428 | * | return props.flags.autoCancel; 429 | | } 430 | | 431 | * | function setAutoCancel(Props memory props, bool value) internal pure { 432 | * | props.flags.autoCancel = value; 433 | | } 434 | | 435 | | // @dev set the order.updatedAtBlock to the current block number 436 | | // @param props Props 437 | * | function touch(Props memory props) internal view { 438 | * | props.setUpdatedAtBlock(Chain.currentBlockNumber()); 439 | * | props.setUpdatedAtTime(Chain.currentTimestamp()); 440 | | } 441 | | } 442 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../utils/Cast.sol"; 7 | | 8 | | import "./Order.sol"; 9 | | 10 | * | library OrderEventUtils { 11 | | using Order for Order.Props; 12 | | 13 | | using EventUtils for EventUtils.AddressItems; 14 | | using EventUtils for EventUtils.UintItems; 15 | | using EventUtils for EventUtils.IntItems; 16 | | using EventUtils for EventUtils.BoolItems; 17 | | using EventUtils for EventUtils.Bytes32Items; 18 | | using EventUtils for EventUtils.BytesItems; 19 | | using EventUtils for EventUtils.StringItems; 20 | | 21 | * | function emitOrderCreated( 22 | | EventEmitter eventEmitter, 23 | | bytes32 key, 24 | | Order.Props memory order 25 | * | ) internal { 26 | * | EventUtils.EventLogData memory eventData; 27 | | 28 | * | eventData.addressItems.initItems(6); 29 | * | eventData.addressItems.setItem(0, "account", order.account()); 30 | * | eventData.addressItems.setItem(1, "receiver", order.receiver()); 31 | * | eventData.addressItems.setItem(2, "callbackContract", order.callbackContract()); 32 | * | eventData.addressItems.setItem(3, "uiFeeReceiver", order.uiFeeReceiver()); 33 | * | eventData.addressItems.setItem(4, "market", order.market()); 34 | * | eventData.addressItems.setItem(5, "initialCollateralToken", order.initialCollateralToken()); 35 | | 36 | * | eventData.addressItems.initArrayItems(1); 37 | * | eventData.addressItems.setItem(0, "swapPath", order.swapPath()); 38 | | 39 | * | eventData.uintItems.initItems(11); 40 | * | eventData.uintItems.setItem(0, "orderType", uint256(order.orderType())); 41 | * | eventData.uintItems.setItem(1, "decreasePositionSwapType", uint256(order.decreasePositionSwapType())); 42 | * | eventData.uintItems.setItem(2, "sizeDeltaUsd", order.sizeDeltaUsd()); 43 | * | eventData.uintItems.setItem(3, "initialCollateralDeltaAmount", order.initialCollateralDeltaAmount()); 44 | * | eventData.uintItems.setItem(4, "triggerPrice", order.triggerPrice()); 45 | * | eventData.uintItems.setItem(5, "acceptablePrice", order.acceptablePrice()); 46 | * | eventData.uintItems.setItem(6, "executionFee", order.executionFee()); 47 | * | eventData.uintItems.setItem(7, "callbackGasLimit", order.callbackGasLimit()); 48 | * | eventData.uintItems.setItem(8, "minOutputAmount", order.minOutputAmount()); 49 | * | eventData.uintItems.setItem(9, "updatedAtBlock", order.updatedAtBlock()); 50 | * | eventData.uintItems.setItem(10, "updatedAtTime", order.updatedAtTime()); 51 | | 52 | * | eventData.boolItems.initItems(3); 53 | * | eventData.boolItems.setItem(0, "isLong", order.isLong()); 54 | * | eventData.boolItems.setItem(1, "shouldUnwrapNativeToken", order.shouldUnwrapNativeToken()); 55 | * | eventData.boolItems.setItem(2, "isFrozen", order.isFrozen()); 56 | | 57 | * | eventData.bytes32Items.initItems(1); 58 | * | eventData.bytes32Items.setItem(0, "key", key); 59 | | 60 | * | eventEmitter.emitEventLog2( 61 | | "OrderCreated", 62 | * | key, 63 | * | Cast.toBytes32(order.account()), 64 | * | eventData 65 | | ); 66 | | } 67 | | 68 | * | function emitOrderExecuted( 69 | | EventEmitter eventEmitter, 70 | | bytes32 key, 71 | | address account, 72 | | Order.SecondaryOrderType secondaryOrderType 73 | * | ) internal { 74 | * | EventUtils.EventLogData memory eventData; 75 | | 76 | * | eventData.bytes32Items.initItems(1); 77 | * | eventData.bytes32Items.setItem(0, "key", key); 78 | | 79 | * | eventData.addressItems.initItems(1); 80 | * | eventData.addressItems.setItem(0, "account", account); 81 | | 82 | * | eventData.uintItems.initItems(1); 83 | * | eventData.uintItems.setItem(0, "secondaryOrderType", uint256(secondaryOrderType)); 84 | | 85 | * | eventEmitter.emitEventLog2( 86 | | "OrderExecuted", 87 | * | key, 88 | * | Cast.toBytes32(account), 89 | * | eventData 90 | | ); 91 | | } 92 | | 93 | | function emitOrderUpdated( 94 | | EventEmitter eventEmitter, 95 | | bytes32 key, 96 | | address account, 97 | | uint256 sizeDeltaUsd, 98 | | uint256 acceptablePrice, 99 | | uint256 triggerPrice, 100 | | uint256 minOutputAmount, 101 | | uint256 updatedAtTime 102 | | ) internal { 103 | | EventUtils.EventLogData memory eventData; 104 | | 105 | | eventData.bytes32Items.initItems(1); 106 | | eventData.bytes32Items.setItem(0, "key", key); 107 | | 108 | | eventData.addressItems.initItems(1); 109 | | eventData.addressItems.setItem(0, "account", account); 110 | | 111 | | eventData.uintItems.initItems(5); 112 | | eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd); 113 | | eventData.uintItems.setItem(1, "acceptablePrice", acceptablePrice); 114 | | eventData.uintItems.setItem(2, "triggerPrice", triggerPrice); 115 | | eventData.uintItems.setItem(3, "minOutputAmount", minOutputAmount); 116 | | eventData.uintItems.setItem(4, "updatedAtTime", updatedAtTime); 117 | | 118 | | eventEmitter.emitEventLog2( 119 | | "OrderUpdated", 120 | | key, 121 | | Cast.toBytes32(account), 122 | | eventData 123 | | ); 124 | | } 125 | | 126 | * | function emitOrderSizeDeltaAutoUpdated( 127 | | EventEmitter eventEmitter, 128 | | bytes32 key, 129 | | uint256 sizeDeltaUsd, 130 | | uint256 nextSizeDeltaUsd 131 | * | ) internal { 132 | * | EventUtils.EventLogData memory eventData; 133 | | 134 | * | eventData.bytes32Items.initItems(1); 135 | * | eventData.bytes32Items.setItem(0, "key", key); 136 | | 137 | * | eventData.uintItems.initItems(2); 138 | * | eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd); 139 | * | eventData.uintItems.setItem(1, "nextSizeDeltaUsd", nextSizeDeltaUsd); 140 | | 141 | * | eventEmitter.emitEventLog1( 142 | | "OrderSizeDeltaAutoUpdated", 143 | * | key, 144 | * | eventData 145 | | ); 146 | | } 147 | | 148 | * | function emitOrderCollateralDeltaAmountAutoUpdated( 149 | | EventEmitter eventEmitter, 150 | | bytes32 key, 151 | | uint256 collateralDeltaAmount, 152 | | uint256 nextCollateralDeltaAmount 153 | * | ) internal { 154 | * | EventUtils.EventLogData memory eventData; 155 | | 156 | * | eventData.bytes32Items.initItems(1); 157 | * | eventData.bytes32Items.setItem(0, "key", key); 158 | | 159 | * | eventData.uintItems.initItems(2); 160 | * | eventData.uintItems.setItem(0, "collateralDeltaAmount", collateralDeltaAmount); 161 | * | eventData.uintItems.setItem(1, "nextCollateralDeltaAmount", nextCollateralDeltaAmount); 162 | | 163 | * | eventEmitter.emitEventLog1( 164 | | "OrderCollateralDeltaAmountAutoUpdated", 165 | * | key, 166 | * | eventData 167 | | ); 168 | | } 169 | | 170 | * | function emitOrderCancelled( 171 | | EventEmitter eventEmitter, 172 | | bytes32 key, 173 | | address account, 174 | | string memory reason, 175 | | bytes memory reasonBytes 176 | * | ) internal { 177 | * | EventUtils.EventLogData memory eventData; 178 | | 179 | * | eventData.bytes32Items.initItems(1); 180 | * | eventData.bytes32Items.setItem(0, "key", key); 181 | | 182 | * | eventData.addressItems.initItems(1); 183 | * | eventData.addressItems.setItem(0, "account", account); 184 | | 185 | * | eventData.stringItems.initItems(1); 186 | * | eventData.stringItems.setItem(0, "reason", reason); 187 | | 188 | * | eventData.bytesItems.initItems(1); 189 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 190 | | 191 | * | eventEmitter.emitEventLog2( 192 | | "OrderCancelled", 193 | * | key, 194 | * | Cast.toBytes32(account), 195 | * | eventData 196 | | ); 197 | | } 198 | | 199 | * | function emitOrderFrozen( 200 | | EventEmitter eventEmitter, 201 | | bytes32 key, 202 | | address account, 203 | | string memory reason, 204 | | bytes memory reasonBytes 205 | * | ) internal { 206 | * | EventUtils.EventLogData memory eventData; 207 | | 208 | * | eventData.bytes32Items.initItems(1); 209 | * | eventData.bytes32Items.setItem(0, "key", key); 210 | | 211 | * | eventData.addressItems.initItems(1); 212 | * | eventData.addressItems.setItem(0, "account", account); 213 | | 214 | * | eventData.stringItems.initItems(1); 215 | * | eventData.stringItems.setItem(0, "reason", reason); 216 | | 217 | * | eventData.bytesItems.initItems(1); 218 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 219 | | 220 | * | eventEmitter.emitEventLog2( 221 | | "OrderFrozen", 222 | * | key, 223 | * | Cast.toBytes32(account), 224 | * | eventData 225 | | ); 226 | | } 227 | | } 228 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Order.sol"; 9 | | 10 | | /** 11 | | * @title OrderStoreUtils 12 | | * @dev Library for order storage functions 13 | | */ 14 | * | library OrderStoreUtils { 15 | | using Order for Order.Props; 16 | | 17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER")); 19 | * | bytes32 internal constant CANCELLATION_RECEIVER = keccak256(abi.encode("CANCELLATION_RECEIVER")); 20 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT")); 21 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER")); 22 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET")); 23 | * | bytes32 internal constant INITIAL_COLLATERAL_TOKEN = keccak256(abi.encode("INITIAL_COLLATERAL_TOKEN")); 24 | * | bytes32 internal constant SWAP_PATH = keccak256(abi.encode("SWAP_PATH")); 25 | | 26 | * | bytes32 internal constant ORDER_TYPE = keccak256(abi.encode("ORDER_TYPE")); 27 | * | bytes32 internal constant DECREASE_POSITION_SWAP_TYPE = keccak256(abi.encode("DECREASE_POSITION_SWAP_TYPE")); 28 | * | bytes32 internal constant SIZE_DELTA_USD = keccak256(abi.encode("SIZE_DELTA_USD")); 29 | * | bytes32 internal constant INITIAL_COLLATERAL_DELTA_AMOUNT = keccak256(abi.encode("INITIAL_COLLATERAL_DELTA_AMOUNT")); 30 | * | bytes32 internal constant TRIGGER_PRICE = keccak256(abi.encode("TRIGGER_PRICE")); 31 | * | bytes32 internal constant ACCEPTABLE_PRICE = keccak256(abi.encode("ACCEPTABLE_PRICE")); 32 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE")); 33 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT")); 34 | * | bytes32 internal constant MIN_OUTPUT_AMOUNT = keccak256(abi.encode("MIN_OUTPUT_AMOUNT")); 35 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK")); 36 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME")); 37 | | 38 | * | bytes32 internal constant IS_LONG = keccak256(abi.encode("IS_LONG")); 39 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN")); 40 | * | bytes32 internal constant IS_FROZEN = keccak256(abi.encode("IS_FROZEN")); 41 | * | bytes32 internal constant AUTO_CANCEL = keccak256(abi.encode("AUTO_CANCEL")); 42 | | 43 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Order.Props memory) { 44 | * | Order.Props memory order; 45 | * | if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) { 46 | | return order; 47 | | } 48 | | 49 | * | order.setAccount(dataStore.getAddress( 50 | * | keccak256(abi.encode(key, ACCOUNT)) 51 | | )); 52 | | 53 | * | order.setReceiver(dataStore.getAddress( 54 | * | keccak256(abi.encode(key, RECEIVER)) 55 | | )); 56 | | 57 | * | order.setCancellationReceiver(dataStore.getAddress( 58 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER)) 59 | | )); 60 | | 61 | * | order.setCallbackContract(dataStore.getAddress( 62 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 63 | | )); 64 | | 65 | * | order.setUiFeeReceiver(dataStore.getAddress( 66 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 67 | | )); 68 | | 69 | * | order.setMarket(dataStore.getAddress( 70 | * | keccak256(abi.encode(key, MARKET)) 71 | | )); 72 | | 73 | * | order.setInitialCollateralToken(dataStore.getAddress( 74 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)) 75 | | )); 76 | | 77 | * | order.setSwapPath(dataStore.getAddressArray( 78 | * | keccak256(abi.encode(key, SWAP_PATH)) 79 | | )); 80 | | 81 | * | order.setOrderType(Order.OrderType(dataStore.getUint( 82 | * | keccak256(abi.encode(key, ORDER_TYPE)) 83 | | ))); 84 | | 85 | * | order.setDecreasePositionSwapType(Order.DecreasePositionSwapType(dataStore.getUint( 86 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)) 87 | | ))); 88 | | 89 | * | order.setSizeDeltaUsd(dataStore.getUint( 90 | * | keccak256(abi.encode(key, SIZE_DELTA_USD)) 91 | | )); 92 | | 93 | * | order.setInitialCollateralDeltaAmount(dataStore.getUint( 94 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)) 95 | | )); 96 | | 97 | * | order.setTriggerPrice(dataStore.getUint( 98 | * | keccak256(abi.encode(key, TRIGGER_PRICE)) 99 | | )); 100 | | 101 | * | order.setAcceptablePrice(dataStore.getUint( 102 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE)) 103 | | )); 104 | | 105 | * | order.setExecutionFee(dataStore.getUint( 106 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 107 | | )); 108 | | 109 | * | order.setCallbackGasLimit(dataStore.getUint( 110 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 111 | | )); 112 | | 113 | * | order.setMinOutputAmount(dataStore.getUint( 114 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)) 115 | | )); 116 | | 117 | * | order.setUpdatedAtBlock(dataStore.getUint( 118 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 119 | | )); 120 | | 121 | * | order.setUpdatedAtTime(dataStore.getUint( 122 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 123 | | )); 124 | | 125 | * | order.setIsLong(dataStore.getBool( 126 | * | keccak256(abi.encode(key, IS_LONG)) 127 | | )); 128 | | 129 | * | order.setShouldUnwrapNativeToken(dataStore.getBool( 130 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 131 | | )); 132 | | 133 | * | order.setIsFrozen(dataStore.getBool( 134 | * | keccak256(abi.encode(key, IS_FROZEN)) 135 | | )); 136 | | 137 | * | order.setAutoCancel(dataStore.getBool( 138 | * | keccak256(abi.encode(key, AUTO_CANCEL)) 139 | | )); 140 | | 141 | * | return order; 142 | | } 143 | | 144 | * | function set(DataStore dataStore, bytes32 key, Order.Props memory order) internal { 145 | * | dataStore.addBytes32( 146 | | Keys.ORDER_LIST, 147 | * | key 148 | | ); 149 | | 150 | * | dataStore.addBytes32( 151 | * | Keys.accountOrderListKey(order.account()), 152 | * | key 153 | | ); 154 | | 155 | * | dataStore.setAddress( 156 | * | keccak256(abi.encode(key, ACCOUNT)), 157 | * | order.account() 158 | | ); 159 | | 160 | * | dataStore.setAddress( 161 | * | keccak256(abi.encode(key, RECEIVER)), 162 | * | order.receiver() 163 | | ); 164 | | 165 | * | dataStore.setAddress( 166 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER)), 167 | * | order.cancellationReceiver() 168 | | ); 169 | | 170 | * | dataStore.setAddress( 171 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)), 172 | * | order.callbackContract() 173 | | ); 174 | | 175 | * | dataStore.setAddress( 176 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)), 177 | * | order.uiFeeReceiver() 178 | | ); 179 | | 180 | * | dataStore.setAddress( 181 | * | keccak256(abi.encode(key, MARKET)), 182 | * | order.market() 183 | | ); 184 | | 185 | * | dataStore.setAddress( 186 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)), 187 | * | order.initialCollateralToken() 188 | | ); 189 | | 190 | * | dataStore.setAddressArray( 191 | * | keccak256(abi.encode(key, SWAP_PATH)), 192 | * | order.swapPath() 193 | | ); 194 | | 195 | * | dataStore.setUint( 196 | * | keccak256(abi.encode(key, ORDER_TYPE)), 197 | * | uint256(order.orderType()) 198 | | ); 199 | | 200 | * | dataStore.setUint( 201 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)), 202 | * | uint256(order.decreasePositionSwapType()) 203 | | ); 204 | | 205 | * | dataStore.setUint( 206 | * | keccak256(abi.encode(key, SIZE_DELTA_USD)), 207 | * | order.sizeDeltaUsd() 208 | | ); 209 | | 210 | * | dataStore.setUint( 211 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)), 212 | * | order.initialCollateralDeltaAmount() 213 | | ); 214 | | 215 | * | dataStore.setUint( 216 | * | keccak256(abi.encode(key, TRIGGER_PRICE)), 217 | * | order.triggerPrice() 218 | | ); 219 | | 220 | * | dataStore.setUint( 221 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE)), 222 | * | order.acceptablePrice() 223 | | ); 224 | | 225 | * | dataStore.setUint( 226 | * | keccak256(abi.encode(key, EXECUTION_FEE)), 227 | * | order.executionFee() 228 | | ); 229 | | 230 | * | dataStore.setUint( 231 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)), 232 | * | order.callbackGasLimit() 233 | | ); 234 | | 235 | * | dataStore.setUint( 236 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)), 237 | * | order.minOutputAmount() 238 | | ); 239 | | 240 | * | dataStore.setUint( 241 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)), 242 | * | order.updatedAtBlock() 243 | | ); 244 | | 245 | * | dataStore.setUint( 246 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)), 247 | * | order.updatedAtTime() 248 | | ); 249 | | 250 | * | dataStore.setBool( 251 | * | keccak256(abi.encode(key, IS_LONG)), 252 | * | order.isLong() 253 | | ); 254 | | 255 | * | dataStore.setBool( 256 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)), 257 | * | order.shouldUnwrapNativeToken() 258 | | ); 259 | | 260 | * | dataStore.setBool( 261 | * | keccak256(abi.encode(key, IS_FROZEN)), 262 | * | order.isFrozen() 263 | | ); 264 | | 265 | * | dataStore.setBool( 266 | * | keccak256(abi.encode(key, AUTO_CANCEL)), 267 | * | order.autoCancel() 268 | | ); 269 | | } 270 | | 271 | * | function remove(DataStore dataStore, bytes32 key, address account) internal { 272 | * | if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) { 273 | | revert Errors.OrderNotFound(key); 274 | | } 275 | | 276 | * | dataStore.removeBytes32( 277 | | Keys.ORDER_LIST, 278 | * | key 279 | | ); 280 | | 281 | * | dataStore.removeBytes32( 282 | * | Keys.accountOrderListKey(account), 283 | * | key 284 | | ); 285 | | 286 | * | dataStore.removeAddress( 287 | * | keccak256(abi.encode(key, ACCOUNT)) 288 | | ); 289 | | 290 | * | dataStore.removeAddress( 291 | * | keccak256(abi.encode(key, RECEIVER)) 292 | | ); 293 | | 294 | * | dataStore.removeAddress( 295 | * | keccak256(abi.encode(key, CANCELLATION_RECEIVER)) 296 | | ); 297 | | 298 | * | dataStore.removeAddress( 299 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 300 | | ); 301 | | 302 | * | dataStore.removeAddress( 303 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 304 | | ); 305 | | 306 | * | dataStore.removeAddress( 307 | * | keccak256(abi.encode(key, MARKET)) 308 | | ); 309 | | 310 | * | dataStore.removeAddress( 311 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)) 312 | | ); 313 | | 314 | * | dataStore.removeAddressArray( 315 | * | keccak256(abi.encode(key, SWAP_PATH)) 316 | | ); 317 | | 318 | * | dataStore.removeUint( 319 | * | keccak256(abi.encode(key, ORDER_TYPE)) 320 | | ); 321 | | 322 | * | dataStore.removeUint( 323 | * | keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)) 324 | | ); 325 | | 326 | * | dataStore.removeUint( 327 | * | keccak256(abi.encode(key, SIZE_DELTA_USD)) 328 | | ); 329 | | 330 | * | dataStore.removeUint( 331 | * | keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)) 332 | | ); 333 | | 334 | * | dataStore.removeUint( 335 | * | keccak256(abi.encode(key, TRIGGER_PRICE)) 336 | | ); 337 | | 338 | * | dataStore.removeUint( 339 | * | keccak256(abi.encode(key, ACCEPTABLE_PRICE)) 340 | | ); 341 | | 342 | * | dataStore.removeUint( 343 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 344 | | ); 345 | | 346 | * | dataStore.removeUint( 347 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 348 | | ); 349 | | 350 | * | dataStore.removeUint( 351 | * | keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)) 352 | | ); 353 | | 354 | * | dataStore.removeUint( 355 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 356 | | ); 357 | | 358 | * | dataStore.removeUint( 359 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 360 | | ); 361 | | 362 | * | dataStore.removeBool( 363 | * | keccak256(abi.encode(key, IS_LONG)) 364 | | ); 365 | | 366 | * | dataStore.removeBool( 367 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 368 | | ); 369 | | 370 | * | dataStore.removeBool( 371 | * | keccak256(abi.encode(key, IS_FROZEN)) 372 | | ); 373 | | 374 | * | dataStore.removeBool( 375 | * | keccak256(abi.encode(key, AUTO_CANCEL)) 376 | | ); 377 | | } 378 | | 379 | | function getOrderCount(DataStore dataStore) internal view returns (uint256) { 380 | | return dataStore.getBytes32Count(Keys.ORDER_LIST); 381 | | } 382 | | 383 | | function getOrderKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 384 | | return dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end); 385 | | } 386 | | 387 | | function getAccountOrderCount(DataStore dataStore, address account) internal view returns (uint256) { 388 | | return dataStore.getBytes32Count(Keys.accountOrderListKey(account)); 389 | | } 390 | | 391 | | function getAccountOrderKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 392 | | return dataStore.getBytes32ValuesAt(Keys.accountOrderListKey(account), start, end); 393 | | } 394 | | } 395 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./AutoCancelUtils.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "./Order.sol"; 10 | | import "./OrderVault.sol"; 11 | | import "./OrderStoreUtils.sol"; 12 | | import "./OrderEventUtils.sol"; 13 | | 14 | | import "../nonce/NonceUtils.sol"; 15 | | import "../oracle/Oracle.sol"; 16 | | import "../oracle/OracleUtils.sol"; 17 | | import "../event/EventEmitter.sol"; 18 | | 19 | | import "./IncreaseOrderUtils.sol"; 20 | | import "./DecreaseOrderUtils.sol"; 21 | | import "./SwapOrderUtils.sol"; 22 | | import "./BaseOrderUtils.sol"; 23 | | 24 | | import "../swap/SwapUtils.sol"; 25 | | 26 | | import "../gas/GasUtils.sol"; 27 | | import "../callback/CallbackUtils.sol"; 28 | | 29 | | import "../utils/Array.sol"; 30 | | import "../utils/AccountUtils.sol"; 31 | | import "../referral/ReferralUtils.sol"; 32 | | 33 | | // @title OrderUtils 34 | | // @dev Library for order functions 35 | * | library OrderUtils { 36 | | using Order for Order.Props; 37 | | using Position for Position.Props; 38 | | using Price for Price.Props; 39 | | using Array for uint256[]; 40 | | 41 | | struct CancelOrderParams { 42 | | DataStore dataStore; 43 | | EventEmitter eventEmitter; 44 | | OrderVault orderVault; 45 | | bytes32 key; 46 | | address keeper; 47 | | uint256 startingGas; 48 | | bool isExternalCall; 49 | | string reason; 50 | | bytes reasonBytes; 51 | | } 52 | | 53 | | // @dev creates an order in the order store 54 | | // @param dataStore DataStore 55 | | // @param eventEmitter EventEmitter 56 | | // @param orderVault OrderVault 57 | | // @param account the order account 58 | | // @param params IBaseOrderUtils.CreateOrderParams 59 | * | function createOrder( 60 | | DataStore dataStore, 61 | | EventEmitter eventEmitter, 62 | | OrderVault orderVault, 63 | | IReferralStorage referralStorage, 64 | | address account, 65 | | IBaseOrderUtils.CreateOrderParams memory params 66 | * | ) internal returns (bytes32) { 67 | * | AccountUtils.validateAccount(account); 68 | | 69 | * | ReferralUtils.setTraderReferralCode(referralStorage, account, params.referralCode); 70 | | 71 | * | uint256 initialCollateralDeltaAmount; 72 | | 73 | * | address wnt = TokenUtils.wnt(dataStore); 74 | | 75 | * | bool shouldRecordSeparateExecutionFeeTransfer = true; 76 | | 77 | * | if ( 78 | * | params.orderType == Order.OrderType.MarketSwap || 79 | * | params.orderType == Order.OrderType.LimitSwap || 80 | * | params.orderType == Order.OrderType.MarketIncrease || 81 | * | params.orderType == Order.OrderType.LimitIncrease 82 | | ) { 83 | | // for swaps and increase orders, the initialCollateralDeltaAmount is set based on the amount of tokens 84 | | // transferred to the orderVault 85 | * | initialCollateralDeltaAmount = orderVault.recordTransferIn(params.addresses.initialCollateralToken); 86 | * | if (params.addresses.initialCollateralToken == wnt) { 87 | * | if (initialCollateralDeltaAmount < params.numbers.executionFee) { 88 | | revert Errors.InsufficientWntAmountForExecutionFee(initialCollateralDeltaAmount, params.numbers.executionFee); 89 | | } 90 | * | initialCollateralDeltaAmount -= params.numbers.executionFee; 91 | * | shouldRecordSeparateExecutionFeeTransfer = false; 92 | | } 93 | * | } else if ( 94 | * | params.orderType == Order.OrderType.MarketDecrease || 95 | * | params.orderType == Order.OrderType.LimitDecrease || 96 | * | params.orderType == Order.OrderType.StopLossDecrease 97 | | ) { 98 | | // for decrease orders, the initialCollateralDeltaAmount is based on the passed in value 99 | * | initialCollateralDeltaAmount = params.numbers.initialCollateralDeltaAmount; 100 | | } else { 101 | | revert Errors.OrderTypeCannotBeCreated(uint256(params.orderType)); 102 | | } 103 | | 104 | * | if (shouldRecordSeparateExecutionFeeTransfer) { 105 | * | uint256 wntAmount = orderVault.recordTransferIn(wnt); 106 | * | if (wntAmount < params.numbers.executionFee) { 107 | | revert Errors.InsufficientWntAmountForExecutionFee(wntAmount, params.numbers.executionFee); 108 | | } 109 | | 110 | * | params.numbers.executionFee = wntAmount; 111 | | } 112 | | 113 | * | if (BaseOrderUtils.isPositionOrder(params.orderType)) { 114 | * | MarketUtils.validatePositionMarket(dataStore, params.addresses.market); 115 | | } 116 | | 117 | | // validate swap path markets 118 | * | MarketUtils.validateSwapPath(dataStore, params.addresses.swapPath); 119 | | 120 | * | Order.Props memory order; 121 | | 122 | * | order.setAccount(account); 123 | * | order.setReceiver(params.addresses.receiver); 124 | * | order.setCancellationReceiver(params.addresses.cancellationReceiver); 125 | * | order.setCallbackContract(params.addresses.callbackContract); 126 | * | order.setMarket(params.addresses.market); 127 | * | order.setInitialCollateralToken(params.addresses.initialCollateralToken); 128 | * | order.setUiFeeReceiver(params.addresses.uiFeeReceiver); 129 | * | order.setSwapPath(params.addresses.swapPath); 130 | * | order.setOrderType(params.orderType); 131 | * | order.setDecreasePositionSwapType(params.decreasePositionSwapType); 132 | * | order.setSizeDeltaUsd(params.numbers.sizeDeltaUsd); 133 | * | order.setInitialCollateralDeltaAmount(initialCollateralDeltaAmount); 134 | * | order.setTriggerPrice(params.numbers.triggerPrice); 135 | * | order.setAcceptablePrice(params.numbers.acceptablePrice); 136 | * | order.setExecutionFee(params.numbers.executionFee); 137 | * | order.setCallbackGasLimit(params.numbers.callbackGasLimit); 138 | * | order.setMinOutputAmount(params.numbers.minOutputAmount); 139 | * | order.setIsLong(params.isLong); 140 | * | order.setShouldUnwrapNativeToken(params.shouldUnwrapNativeToken); 141 | * | order.setAutoCancel(params.autoCancel); 142 | | 143 | * | AccountUtils.validateReceiver(order.receiver()); 144 | | 145 | * | CallbackUtils.validateCallbackGasLimit(dataStore, order.callbackGasLimit()); 146 | | 147 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteOrderGasLimit(dataStore, order); 148 | * | uint256 oraclePriceCount = GasUtils.estimateOrderOraclePriceCount(params.addresses.swapPath.length); 149 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, order.executionFee(), oraclePriceCount); 150 | | 151 | * | bytes32 key = NonceUtils.getNextKey(dataStore); 152 | | 153 | * | order.touch(); 154 | | 155 | * | BaseOrderUtils.validateNonEmptyOrder(order); 156 | * | OrderStoreUtils.set(dataStore, key, order); 157 | | 158 | * | updateAutoCancelList(dataStore, key, order, order.autoCancel()); 159 | * | validateTotalCallbackGasLimitForAutoCancelOrders(dataStore, order); 160 | | 161 | * | OrderEventUtils.emitOrderCreated(eventEmitter, key, order); 162 | | 163 | * | return key; 164 | | } 165 | | 166 | * | function cancelOrder(CancelOrderParams memory params) internal { 167 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 168 | * | if (params.isExternalCall) { 169 | * | params.startingGas -= gasleft() / 63; 170 | | } 171 | | 172 | * | Order.Props memory order = OrderStoreUtils.get(params.dataStore, params.key); 173 | * | BaseOrderUtils.validateNonEmptyOrder(order); 174 | | 175 | * | OrderStoreUtils.remove(params.dataStore, params.key, order.account()); 176 | | 177 | * | if (BaseOrderUtils.isIncreaseOrder(order.orderType()) || BaseOrderUtils.isSwapOrder(order.orderType())) { 178 | * | if (order.initialCollateralDeltaAmount() > 0) { 179 | * | address cancellationReceiver = order.cancellationReceiver(); 180 | * | if (cancellationReceiver == address(0)) { 181 | | cancellationReceiver = order.account(); 182 | | } 183 | | 184 | * | params.orderVault.transferOut( 185 | * | order.initialCollateralToken(), 186 | * | cancellationReceiver, 187 | * | order.initialCollateralDeltaAmount(), 188 | * | order.shouldUnwrapNativeToken() 189 | | ); 190 | | } 191 | | } 192 | | 193 | * | updateAutoCancelList(params.dataStore, params.key, order, false); 194 | | 195 | * | OrderEventUtils.emitOrderCancelled( 196 | * | params.eventEmitter, 197 | * | params.key, 198 | * | order.account(), 199 | * | params.reason, 200 | * | params.reasonBytes 201 | | ); 202 | | 203 | * | address executionFeeReceiver = order.cancellationReceiver(); 204 | | 205 | * | if (executionFeeReceiver == address(0)) { 206 | | executionFeeReceiver = order.receiver(); 207 | | } 208 | | 209 | * | EventUtils.EventLogData memory eventData; 210 | * | CallbackUtils.afterOrderCancellation(params.key, order, eventData); 211 | | 212 | * | GasUtils.payExecutionFee( 213 | * | params.dataStore, 214 | * | params.eventEmitter, 215 | * | params.orderVault, 216 | * | params.key, 217 | * | order.callbackContract(), 218 | * | order.executionFee(), 219 | * | params.startingGas, 220 | * | GasUtils.estimateOrderOraclePriceCount(order.swapPath().length), 221 | * | params.keeper, 222 | * | executionFeeReceiver 223 | | ); 224 | | } 225 | | 226 | | // @dev freezes an order 227 | | // @param dataStore DataStore 228 | | // @param eventEmitter EventEmitter 229 | | // @param orderVault OrderVault 230 | | // @param key the key of the order to freeze 231 | | // @param keeper the keeper sending the transaction 232 | | // @param startingGas the starting gas of the transaction 233 | | // @param reason the reason the order was frozen 234 | * | function freezeOrder( 235 | | DataStore dataStore, 236 | | EventEmitter eventEmitter, 237 | | OrderVault orderVault, 238 | | bytes32 key, 239 | | address keeper, 240 | | uint256 startingGas, 241 | | string memory reason, 242 | | bytes memory reasonBytes 243 | * | ) internal { 244 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 245 | * | startingGas -= gasleft() / 63; 246 | | 247 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 248 | * | BaseOrderUtils.validateNonEmptyOrder(order); 249 | | 250 | * | if (order.isFrozen()) { 251 | | revert Errors.OrderAlreadyFrozen(); 252 | | } 253 | | 254 | * | order.setExecutionFee(0); 255 | * | order.setIsFrozen(true); 256 | * | OrderStoreUtils.set(dataStore, key, order); 257 | | 258 | * | OrderEventUtils.emitOrderFrozen( 259 | * | eventEmitter, 260 | * | key, 261 | * | order.account(), 262 | * | reason, 263 | * | reasonBytes 264 | | ); 265 | | 266 | * | EventUtils.EventLogData memory eventData; 267 | * | CallbackUtils.afterOrderFrozen(key, order, eventData); 268 | | 269 | * | GasUtils.payExecutionFee( 270 | * | dataStore, 271 | * | eventEmitter, 272 | * | orderVault, 273 | * | key, 274 | * | order.callbackContract(), 275 | * | order.executionFee(), 276 | * | startingGas, 277 | * | GasUtils.estimateOrderOraclePriceCount(order.swapPath().length), 278 | * | keeper, 279 | * | order.receiver() 280 | | ); 281 | | } 282 | | 283 | * | function clearAutoCancelOrders( 284 | | DataStore dataStore, 285 | | EventEmitter eventEmitter, 286 | | OrderVault orderVault, 287 | | bytes32 positionKey, 288 | | address keeper 289 | * | ) internal { 290 | * | bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey); 291 | | 292 | * | for (uint256 i; i < orderKeys.length; i++) { 293 | | cancelOrder( 294 | | CancelOrderParams( 295 | | dataStore, 296 | | eventEmitter, 297 | | orderVault, 298 | | orderKeys[i], 299 | | keeper, // keeper 300 | | gasleft(), // startingGas 301 | | false, // isExternalCall 302 | | "AUTO_CANCEL", // reason 303 | | "" // reasonBytes 304 | | ) 305 | | ); 306 | | } 307 | | } 308 | | 309 | * | function updateAutoCancelList(DataStore dataStore, bytes32 orderKey, Order.Props memory order, bool shouldAdd) internal { 310 | * | if ( 311 | * | order.orderType() != Order.OrderType.LimitDecrease && 312 | * | order.orderType() != Order.OrderType.StopLossDecrease 313 | | ) { 314 | * | return; 315 | | } 316 | | 317 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(order); 318 | | 319 | * | if (shouldAdd) { 320 | * | AutoCancelUtils.addAutoCancelOrderKey(dataStore, positionKey, orderKey); 321 | | } else { 322 | * | AutoCancelUtils.removeAutoCancelOrderKey(dataStore, positionKey, orderKey); 323 | | } 324 | | } 325 | | 326 | * | function validateTotalCallbackGasLimitForAutoCancelOrders(DataStore dataStore, Order.Props memory order) internal view { 327 | * | if ( 328 | * | order.orderType() != Order.OrderType.LimitDecrease && 329 | * | order.orderType() != Order.OrderType.StopLossDecrease 330 | | ) { 331 | * | return; 332 | | } 333 | | 334 | * | bytes32 positionKey = BaseOrderUtils.getPositionKey(order); 335 | * | uint256 maxTotal = dataStore.getUint(Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS); 336 | * | uint256 total = getTotalCallbackGasLimitForAutoCancelOrders(dataStore, positionKey); 337 | | 338 | * | if (total > maxTotal) { 339 | | revert Errors.MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(total, maxTotal); 340 | | } 341 | | } 342 | | 343 | * | function getTotalCallbackGasLimitForAutoCancelOrders(DataStore dataStore, bytes32 positionKey) internal view returns (uint256) { 344 | * | bytes32[] memory orderKeys = AutoCancelUtils.getAutoCancelOrderKeys(dataStore, positionKey); 345 | | 346 | * | uint256 total; 347 | | 348 | * | for (uint256 i; i < orderKeys.length; i++) { 349 | * | total += dataStore.getUint( 350 | * | keccak256(abi.encode(orderKeys[i], OrderStoreUtils.CALLBACK_GAS_LIMIT)) 351 | | ); 352 | | } 353 | | 354 | * | return total; 355 | | } 356 | | } 357 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/OrderVault.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../bank/StrictBank.sol"; 6 | | 7 | | // @title OrderVault 8 | | // @dev Vault for orders 9 | * | contract OrderVault is StrictBank { 10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {} 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/order/SwapOrderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseOrderUtils.sol"; 6 | | import "../swap/SwapUtils.sol"; 7 | | import "../order/OrderStoreUtils.sol"; 8 | | 9 | | // @title SwapOrderUtils 10 | | // @dev Library for functions to help with processing a swap order 11 | * | library SwapOrderUtils { 12 | | using Order for Order.Props; 13 | | using Array for uint256[]; 14 | | 15 | | using EventUtils for EventUtils.AddressItems; 16 | | using EventUtils for EventUtils.UintItems; 17 | | using EventUtils for EventUtils.IntItems; 18 | | using EventUtils for EventUtils.BoolItems; 19 | | using EventUtils for EventUtils.Bytes32Items; 20 | | using EventUtils for EventUtils.BytesItems; 21 | | using EventUtils for EventUtils.StringItems; 22 | | 23 | | // @dev process a swap order 24 | | // @param params BaseOrderUtils.ExecuteOrderParams 25 | * | function processOrder(BaseOrderUtils.ExecuteOrderParams memory params) internal returns (EventUtils.EventLogData memory) { 26 | * | if (params.order.market() != address(0)) { 27 | | revert Errors.UnexpectedMarket(); 28 | | } 29 | | 30 | * | if (params.minOracleTimestamp < params.order.updatedAtTime()) { 31 | | revert Errors.OracleTimestampsAreSmallerThanRequired( 32 | | params.minOracleTimestamp, 33 | | params.order.updatedAtTime() 34 | | ); 35 | | } 36 | | 37 | * | uint256 requestExpirationTime = params.contracts.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 38 | | 39 | * | if ( 40 | * | params.order.orderType() == Order.OrderType.MarketSwap && 41 | * | params.maxOracleTimestamp > params.order.updatedAtTime() + requestExpirationTime 42 | | ) { 43 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 44 | * | params.maxOracleTimestamp, 45 | * | params.order.updatedAtTime(), 46 | * | requestExpirationTime 47 | | ); 48 | | } 49 | | 50 | * | (address outputToken, uint256 outputAmount) = SwapUtils.swap(SwapUtils.SwapParams( 51 | * | params.contracts.dataStore, 52 | * | params.contracts.eventEmitter, 53 | * | params.contracts.oracle, 54 | * | params.contracts.orderVault, 55 | * | params.key, 56 | * | params.order.initialCollateralToken(), 57 | * | params.order.initialCollateralDeltaAmount(), 58 | * | params.swapPathMarkets, 59 | * | params.order.minOutputAmount(), 60 | * | params.order.receiver(), 61 | * | params.order.uiFeeReceiver(), 62 | * | params.order.shouldUnwrapNativeToken() 63 | | )); 64 | | 65 | * | EventUtils.EventLogData memory eventData; 66 | * | eventData.addressItems.initItems(1); 67 | * | eventData.addressItems.setItem(0, "outputToken", outputToken); 68 | * | eventData.uintItems.initItems(1); 69 | * | eventData.uintItems.setItem(0, "outputAmount", outputAmount); 70 | * | return eventData; 71 | | } 72 | | } 73 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionCollateralUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/Precision.sol"; 6 | | import "../error/ErrorUtils.sol"; 7 | | 8 | | import "../data/DataStore.sol"; 9 | | import "../event/EventEmitter.sol"; 10 | | 11 | | import "../oracle/Oracle.sol"; 12 | | import "../pricing/PositionPricingUtils.sol"; 13 | | 14 | | import "./Position.sol"; 15 | | import "./PositionEventUtils.sol"; 16 | | import "./PositionStoreUtils.sol"; 17 | | import "./PositionUtils.sol"; 18 | | import "../order/BaseOrderUtils.sol"; 19 | | import "../order/OrderEventUtils.sol"; 20 | | 21 | | import "../swap/SwapUtils.sol"; 22 | | import "./DecreasePositionSwapUtils.sol"; 23 | | 24 | | // @title DecreasePositionCollateralUtils 25 | | // @dev Library for functions to help with the calculations when decreasing a position 26 | * | library DecreasePositionCollateralUtils { 27 | | using SafeCast for uint256; 28 | | using SafeCast for int256; 29 | | 30 | | using Position for Position.Props; 31 | | using Order for Order.Props; 32 | | using Price for Price.Props; 33 | | 34 | | using EventUtils for EventUtils.AddressItems; 35 | | using EventUtils for EventUtils.UintItems; 36 | | using EventUtils for EventUtils.IntItems; 37 | | using EventUtils for EventUtils.BoolItems; 38 | | using EventUtils for EventUtils.Bytes32Items; 39 | | using EventUtils for EventUtils.BytesItems; 40 | | using EventUtils for EventUtils.StringItems; 41 | | 42 | | struct ProcessCollateralCache { 43 | | bool isInsolventCloseAllowed; 44 | | bool wasSwapped; 45 | | uint256 swapOutputAmount; 46 | | PayForCostResult result; 47 | | } 48 | | 49 | | struct PayForCostResult { 50 | | uint256 amountPaidInCollateralToken; 51 | | uint256 amountPaidInSecondaryOutputToken; 52 | | uint256 remainingCostUsd; 53 | | } 54 | | 55 | | // @dev handle the collateral changes of the position 56 | | // @param params PositionUtils.UpdatePositionParams 57 | | // @param cache DecreasePositionCache 58 | | // @return (PositionUtils.DecreasePositionCollateralValues, PositionPricingUtils.PositionFees) 59 | * | function processCollateral( 60 | | PositionUtils.UpdatePositionParams memory params, 61 | | PositionUtils.DecreasePositionCache memory cache 62 | | ) internal returns ( 63 | * | PositionUtils.DecreasePositionCollateralValues memory, 64 | * | PositionPricingUtils.PositionFees memory 65 | | ) { 66 | * | ProcessCollateralCache memory collateralCache; 67 | * | PositionUtils.DecreasePositionCollateralValues memory values; 68 | | 69 | * | values.output.outputToken = params.position.collateralToken(); 70 | * | values.output.secondaryOutputToken = cache.pnlToken; 71 | | 72 | | // only allow insolvent closing if it is a liquidation or ADL order 73 | | // isInsolventCloseAllowed is used in handleEarlyReturn to determine 74 | | // whether the txn should revert if the remainingCostUsd is below zero 75 | | // 76 | | // for isInsolventCloseAllowed to be true, the sizeDeltaUsd must equal 77 | | // the position size, otherwise there may be pending positive pnl that 78 | | // could be used to pay for fees and the position would be undercharged 79 | | // if the position is not fully closed 80 | | // 81 | | // for ADLs it may be possible that a position needs to be closed by a larger 82 | | // size to fully pay for fees, but closing by that larger size could cause a PnlOvercorrected 83 | | // error to be thrown in AdlHandler, this case should be rare 84 | * | collateralCache.isInsolventCloseAllowed = 85 | * | params.order.sizeDeltaUsd() == params.position.sizeInUsd() && 86 | | ( 87 | * | BaseOrderUtils.isLiquidationOrder(params.order.orderType()) || 88 | * | params.secondaryOrderType == Order.SecondaryOrderType.Adl 89 | | ); 90 | | 91 | | // in case price impact is too high it is capped and the difference is made to be claimable 92 | | // the execution price is based on the capped price impact so it may be a better price than what it should be 93 | | // priceImpactDiffUsd is the difference between the maximum price impact and the originally calculated price impact 94 | | // e.g. if the originally calculated price impact is -$100, but the capped price impact is -$80 95 | | // then priceImpactDiffUsd would be $20 96 | * | (values.priceImpactUsd, values.priceImpactDiffUsd, values.executionPrice) = PositionUtils.getExecutionPriceForDecrease(params, cache.prices.indexTokenPrice); 97 | | 98 | | // the totalPositionPnl is calculated based on the current indexTokenPrice instead of the executionPrice 99 | | // since the executionPrice factors in price impact which should be accounted for separately 100 | | // the sizeDeltaInTokens is calculated as position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd() 101 | | // the basePnlUsd is the pnl to be realized, and is calculated as: 102 | | // totalPositionPnl * sizeDeltaInTokens / position.sizeInTokens() 103 | * | (values.basePnlUsd, values.uncappedBasePnlUsd, values.sizeDeltaInTokens) = PositionUtils.getPositionPnlUsd( 104 | * | params.contracts.dataStore, 105 | * | params.market, 106 | * | cache.prices, 107 | * | params.position, 108 | * | params.order.sizeDeltaUsd() 109 | | ); 110 | | 111 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams( 112 | * | params.contracts.dataStore, // dataStore 113 | * | params.contracts.referralStorage, // referralStorage 114 | * | params.position, // position 115 | * | cache.collateralTokenPrice, // collateralTokenPrice 116 | * | values.priceImpactUsd > 0, // forPositiveImpact 117 | * | params.market.longToken, // longToken 118 | * | params.market.shortToken, // shortToken 119 | * | params.order.sizeDeltaUsd(), // sizeDeltaUsd 120 | * | params.order.uiFeeReceiver() // uiFeeReceiver 121 | | ); 122 | | 123 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees( 124 | * | getPositionFeesParams 125 | | ); 126 | | 127 | | // if the pnl is positive, deduct the pnl amount from the pool 128 | * | if (values.basePnlUsd > 0) { 129 | | // use pnlTokenPrice.max to minimize the tokens paid out 130 | * | uint256 deductionAmountForPool = values.basePnlUsd.toUint256() / cache.pnlTokenPrice.max; 131 | | 132 | * | MarketUtils.applyDeltaToPoolAmount( 133 | * | params.contracts.dataStore, 134 | * | params.contracts.eventEmitter, 135 | * | params.market, 136 | * | cache.pnlToken, 137 | * | -deductionAmountForPool.toInt256() 138 | | ); 139 | | 140 | * | if (values.output.outputToken == cache.pnlToken) { 141 | * | values.output.outputAmount += deductionAmountForPool; 142 | | } else { 143 | * | values.output.secondaryOutputAmount += deductionAmountForPool; 144 | | } 145 | | } 146 | | 147 | * | if (values.priceImpactUsd > 0) { 148 | | // use indexTokenPrice.min to maximize the position impact pool reduction 149 | | uint256 deductionAmountForImpactPool = Calc.roundUpDivision(values.priceImpactUsd.toUint256(), cache.prices.indexTokenPrice.min); 150 | | 151 | | MarketUtils.applyDeltaToPositionImpactPool( 152 | | params.contracts.dataStore, 153 | | params.contracts.eventEmitter, 154 | | params.market.marketToken, 155 | | -deductionAmountForImpactPool.toInt256() 156 | | ); 157 | | 158 | | // use pnlTokenPrice.max to minimize the payout from the pool 159 | | // some impact pool value may be transferred to the market token pool if there is a 160 | | // large spread between min and max prices 161 | | // since if there is a positive priceImpactUsd, the impact pool would be reduced using indexTokenPrice.min to 162 | | // maximize the deduction value, while the market token pool is reduced using the pnlTokenPrice.max to minimize 163 | | // the deduction value 164 | | // the pool value is calculated by subtracting the worth of the tokens in the position impact pool 165 | | // so this transfer of value would increase the price of the market token 166 | | uint256 deductionAmountForPool = values.priceImpactUsd.toUint256() / cache.pnlTokenPrice.max; 167 | | 168 | | MarketUtils.applyDeltaToPoolAmount( 169 | | params.contracts.dataStore, 170 | | params.contracts.eventEmitter, 171 | | params.market, 172 | | cache.pnlToken, 173 | | -deductionAmountForPool.toInt256() 174 | | ); 175 | | 176 | | if (values.output.outputToken == cache.pnlToken) { 177 | | values.output.outputAmount += deductionAmountForPool; 178 | | } else { 179 | | values.output.secondaryOutputAmount += deductionAmountForPool; 180 | | } 181 | | } 182 | | 183 | | // swap profit to the collateral token 184 | | // if the decreasePositionSwapType was set to NoSwap or if the swap fails due 185 | | // to insufficient liquidity or other reasons then it is possible that 186 | | // the profit remains in a different token from the collateral token 187 | * | (collateralCache.wasSwapped, collateralCache.swapOutputAmount) = DecreasePositionSwapUtils.swapProfitToCollateralToken( 188 | * | params, 189 | * | cache.pnlToken, 190 | * | values.output.secondaryOutputAmount 191 | | ); 192 | | 193 | | // if the swap was successful the profit should have been swapped 194 | | // to the collateral token 195 | * | if (collateralCache.wasSwapped) { 196 | * | values.output.outputAmount += collateralCache.swapOutputAmount; 197 | * | values.output.secondaryOutputAmount = 0; 198 | | } 199 | | 200 | * | values.remainingCollateralAmount = params.position.collateralAmount(); 201 | | 202 | | // pay for funding fees 203 | * | (values, collateralCache.result) = payForCost( 204 | * | params, 205 | * | values, 206 | * | cache.prices, 207 | * | cache.collateralTokenPrice, 208 | | // use collateralTokenPrice.min because the payForCost 209 | | // will divide the USD value by the price.min as well 210 | * | fees.funding.fundingFeeAmount * cache.collateralTokenPrice.min 211 | | ); 212 | | 213 | * | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) { 214 | | address holdingAddress = params.contracts.dataStore.getAddress(Keys.HOLDING_ADDRESS); 215 | | if (holdingAddress == address(0)) { 216 | | revert Errors.EmptyHoldingAddress(); 217 | | } 218 | | 219 | | // send the funding fee amount to the holding address 220 | | // this funding fee amount should be swapped to the required token 221 | | // and the resulting tokens should be deposited back into the pool 222 | | MarketUtils.incrementClaimableCollateralAmount( 223 | | params.contracts.dataStore, 224 | | params.contracts.eventEmitter, 225 | | params.market.marketToken, 226 | | values.output.secondaryOutputToken, 227 | | holdingAddress, 228 | | collateralCache.result.amountPaidInSecondaryOutputToken 229 | | ); 230 | | } 231 | | 232 | * | if (collateralCache.result.amountPaidInCollateralToken < fees.funding.fundingFeeAmount) { 233 | | // the case where this is insufficient collateral to pay funding fees 234 | | // should be rare, and the difference should be small 235 | | // in case it happens, the pool should be topped up with the required amount using 236 | | // the claimable amount sent to the holding address, an insurance fund, or similar mechanism 237 | * | PositionEventUtils.emitInsufficientFundingFeePayment( 238 | * | params.contracts.eventEmitter, 239 | * | params.market.marketToken, 240 | * | params.position.collateralToken(), 241 | * | fees.funding.fundingFeeAmount, 242 | * | collateralCache.result.amountPaidInCollateralToken, 243 | * | collateralCache.result.amountPaidInSecondaryOutputToken 244 | | ); 245 | | } 246 | | 247 | * | if (collateralCache.result.remainingCostUsd > 0) { 248 | * | return handleEarlyReturn( 249 | * | params, 250 | * | values, 251 | * | fees, 252 | * | collateralCache, 253 | | "funding" 254 | | ); 255 | | } 256 | | 257 | | // pay for negative pnl 258 | * | if (values.basePnlUsd < 0) { 259 | * | (values, collateralCache.result) = payForCost( 260 | * | params, 261 | * | values, 262 | * | cache.prices, 263 | * | cache.collateralTokenPrice, 264 | * | (-values.basePnlUsd).toUint256() 265 | | ); 266 | | 267 | * | if (collateralCache.result.amountPaidInCollateralToken > 0) { 268 | * | MarketUtils.applyDeltaToPoolAmount( 269 | * | params.contracts.dataStore, 270 | * | params.contracts.eventEmitter, 271 | * | params.market, 272 | * | params.position.collateralToken(), 273 | * | collateralCache.result.amountPaidInCollateralToken.toInt256() 274 | | ); 275 | | } 276 | | 277 | * | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) { 278 | | MarketUtils.applyDeltaToPoolAmount( 279 | | params.contracts.dataStore, 280 | | params.contracts.eventEmitter, 281 | | params.market, 282 | | values.output.secondaryOutputToken, 283 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256() 284 | | ); 285 | | } 286 | | 287 | * | if (collateralCache.result.remainingCostUsd > 0) { 288 | * | return handleEarlyReturn( 289 | * | params, 290 | * | values, 291 | * | fees, 292 | * | collateralCache, 293 | | "pnl" 294 | | ); 295 | | } 296 | | } 297 | | 298 | | // pay for fees 299 | * | (values, collateralCache.result) = payForCost( 300 | * | params, 301 | * | values, 302 | * | cache.prices, 303 | * | cache.collateralTokenPrice, 304 | | // use collateralTokenPrice.min because the payForCost 305 | | // will divide the USD value by the price.min as well 306 | * | fees.totalCostAmountExcludingFunding * cache.collateralTokenPrice.min 307 | | ); 308 | | 309 | | // if fees were fully paid in the collateral token, update the pool and claimable fee amounts 310 | * | if (collateralCache.result.remainingCostUsd == 0 && collateralCache.result.amountPaidInSecondaryOutputToken == 0) { 311 | | // there may be a large amount of borrowing fees that could have been accumulated 312 | | // these fees could cause the pool to become unbalanced, price impact is not paid for causing 313 | | // this imbalance 314 | | // the swap impact pool should be built up so that it can be used to pay for positive price impact 315 | | // for re-balancing to help handle this case 316 | * | MarketUtils.applyDeltaToPoolAmount( 317 | * | params.contracts.dataStore, 318 | * | params.contracts.eventEmitter, 319 | * | params.market, 320 | * | params.position.collateralToken(), 321 | * | fees.feeAmountForPool.toInt256() 322 | | ); 323 | | 324 | * | FeeUtils.incrementClaimableFeeAmount( 325 | * | params.contracts.dataStore, 326 | * | params.contracts.eventEmitter, 327 | * | params.market.marketToken, 328 | * | params.position.collateralToken(), 329 | * | fees.feeReceiverAmount, 330 | | Keys.POSITION_FEE_TYPE 331 | | ); 332 | | 333 | * | FeeUtils.incrementClaimableUiFeeAmount( 334 | * | params.contracts.dataStore, 335 | * | params.contracts.eventEmitter, 336 | * | params.order.uiFeeReceiver(), 337 | * | params.market.marketToken, 338 | * | params.position.collateralToken(), 339 | * | fees.ui.uiFeeAmount, 340 | | Keys.UI_POSITION_FEE_TYPE 341 | | ); 342 | | } else { 343 | | // the fees are expected to be paid in the collateral token 344 | | // if there are insufficient funds to pay for fees entirely in the collateral token 345 | | // then credit the fee amount entirely to the pool 346 | | if (collateralCache.result.amountPaidInCollateralToken > 0) { 347 | | MarketUtils.applyDeltaToPoolAmount( 348 | | params.contracts.dataStore, 349 | | params.contracts.eventEmitter, 350 | | params.market, 351 | | params.position.collateralToken(), 352 | | collateralCache.result.amountPaidInCollateralToken.toInt256() 353 | | ); 354 | | } 355 | | 356 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) { 357 | | MarketUtils.applyDeltaToPoolAmount( 358 | | params.contracts.dataStore, 359 | | params.contracts.eventEmitter, 360 | | params.market, 361 | | values.output.secondaryOutputToken, 362 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256() 363 | | ); 364 | | } 365 | | 366 | | // empty the fees since the amount was entirely paid to the pool instead of for fees 367 | | // it is possible for the txn execution to still complete even in this case 368 | | // as long as the remainingCostUsd is still zero 369 | | fees = getEmptyFees(fees); 370 | | } 371 | | 372 | * | if (collateralCache.result.remainingCostUsd > 0) { 373 | | return handleEarlyReturn( 374 | | params, 375 | | values, 376 | | fees, 377 | | collateralCache, 378 | | "fees" 379 | | ); 380 | | } 381 | | 382 | | // pay for negative price impact 383 | * | if (values.priceImpactUsd < 0) { 384 | | (values, collateralCache.result) = payForCost( 385 | | params, 386 | | values, 387 | | cache.prices, 388 | | cache.collateralTokenPrice, 389 | | (-values.priceImpactUsd).toUint256() 390 | | ); 391 | | 392 | | if (collateralCache.result.amountPaidInCollateralToken > 0) { 393 | | MarketUtils.applyDeltaToPoolAmount( 394 | | params.contracts.dataStore, 395 | | params.contracts.eventEmitter, 396 | | params.market, 397 | | params.position.collateralToken(), 398 | | collateralCache.result.amountPaidInCollateralToken.toInt256() 399 | | ); 400 | | 401 | | MarketUtils.applyDeltaToPositionImpactPool( 402 | | params.contracts.dataStore, 403 | | params.contracts.eventEmitter, 404 | | params.market.marketToken, 405 | | (collateralCache.result.amountPaidInCollateralToken * cache.collateralTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256() 406 | | ); 407 | | } 408 | | 409 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) { 410 | | MarketUtils.applyDeltaToPoolAmount( 411 | | params.contracts.dataStore, 412 | | params.contracts.eventEmitter, 413 | | params.market, 414 | | values.output.secondaryOutputToken, 415 | | collateralCache.result.amountPaidInSecondaryOutputToken.toInt256() 416 | | ); 417 | | 418 | | MarketUtils.applyDeltaToPositionImpactPool( 419 | | params.contracts.dataStore, 420 | | params.contracts.eventEmitter, 421 | | params.market.marketToken, 422 | | (collateralCache.result.amountPaidInSecondaryOutputToken * cache.pnlTokenPrice.min / cache.prices.indexTokenPrice.max).toInt256() 423 | | ); 424 | | } 425 | | 426 | | if (collateralCache.result.remainingCostUsd > 0) { 427 | | return handleEarlyReturn( 428 | | params, 429 | | values, 430 | | fees, 431 | | collateralCache, 432 | | "impact" 433 | | ); 434 | | } 435 | | } 436 | | 437 | | // pay for price impact diff 438 | * | if (values.priceImpactDiffUsd > 0) { 439 | | (values, collateralCache.result) = payForCost( 440 | | params, 441 | | values, 442 | | cache.prices, 443 | | cache.collateralTokenPrice, 444 | | values.priceImpactDiffUsd 445 | | ); 446 | | 447 | | if (collateralCache.result.amountPaidInCollateralToken > 0) { 448 | | MarketUtils.incrementClaimableCollateralAmount( 449 | | params.contracts.dataStore, 450 | | params.contracts.eventEmitter, 451 | | params.market.marketToken, 452 | | params.position.collateralToken(), 453 | | params.order.account(), 454 | | collateralCache.result.amountPaidInCollateralToken 455 | | ); 456 | | } 457 | | 458 | | if (collateralCache.result.amountPaidInSecondaryOutputToken > 0) { 459 | | MarketUtils.incrementClaimableCollateralAmount( 460 | | params.contracts.dataStore, 461 | | params.contracts.eventEmitter, 462 | | params.market.marketToken, 463 | | values.output.secondaryOutputToken, 464 | | params.order.account(), 465 | | collateralCache.result.amountPaidInSecondaryOutputToken 466 | | ); 467 | | } 468 | | 469 | | if (collateralCache.result.remainingCostUsd > 0) { 470 | | return handleEarlyReturn( 471 | | params, 472 | | values, 473 | | fees, 474 | | collateralCache, 475 | | "diff" 476 | | ); 477 | | } 478 | | } 479 | | 480 | | // the priceImpactDiffUsd has been deducted from the output amount or the position's collateral 481 | | // to reduce the chance that the position's collateral is reduced by an unexpected amount, adjust the 482 | | // initialCollateralDeltaAmount by the priceImpactDiffAmount 483 | | // this would also help to prevent the position's leverage from being unexpectedly increased 484 | | // 485 | | // note that this calculation may not be entirely accurate since it is possible that the priceImpactDiffUsd 486 | | // could have been paid with one of or a combination of collateral / outputAmount / secondaryOutputAmount 487 | * | if (params.order.initialCollateralDeltaAmount() > 0 && values.priceImpactDiffUsd > 0) { 488 | | uint256 initialCollateralDeltaAmount = params.order.initialCollateralDeltaAmount(); 489 | | 490 | | uint256 priceImpactDiffAmount = values.priceImpactDiffUsd / cache.collateralTokenPrice.min; 491 | | if (initialCollateralDeltaAmount > priceImpactDiffAmount) { 492 | | params.order.setInitialCollateralDeltaAmount(initialCollateralDeltaAmount - priceImpactDiffAmount); 493 | | } else { 494 | | params.order.setInitialCollateralDeltaAmount(0); 495 | | } 496 | | 497 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated( 498 | | params.contracts.eventEmitter, 499 | | params.orderKey, 500 | | initialCollateralDeltaAmount, // collateralDeltaAmount 501 | | params.order.initialCollateralDeltaAmount() // nextCollateralDeltaAmount 502 | | ); 503 | | } 504 | | 505 | | // cap the withdrawable amount to the remainingCollateralAmount 506 | * | if (params.order.initialCollateralDeltaAmount() > values.remainingCollateralAmount) { 507 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated( 508 | | params.contracts.eventEmitter, 509 | | params.orderKey, 510 | | params.order.initialCollateralDeltaAmount(), // collateralDeltaAmount 511 | | values.remainingCollateralAmount // nextCollateralDeltaAmount 512 | | ); 513 | | 514 | | params.order.setInitialCollateralDeltaAmount(values.remainingCollateralAmount); 515 | | } 516 | | 517 | * | if (params.order.initialCollateralDeltaAmount() > 0) { 518 | * | values.remainingCollateralAmount -= params.order.initialCollateralDeltaAmount(); 519 | * | values.output.outputAmount += params.order.initialCollateralDeltaAmount(); 520 | | } 521 | | 522 | * | return (values, fees); 523 | | } 524 | | 525 | * | function payForCost( 526 | | PositionUtils.UpdatePositionParams memory params, 527 | | PositionUtils.DecreasePositionCollateralValues memory values, 528 | | MarketUtils.MarketPrices memory prices, 529 | | Price.Props memory collateralTokenPrice, 530 | | uint256 costUsd 531 | * | ) internal pure returns (PositionUtils.DecreasePositionCollateralValues memory, PayForCostResult memory) { 532 | * | PayForCostResult memory result; 533 | | 534 | * | if (costUsd == 0) { return (values, result); } 535 | | 536 | * | uint256 remainingCostInOutputToken = Calc.roundUpDivision(costUsd, collateralTokenPrice.min); 537 | | 538 | * | if (values.output.outputAmount > 0) { 539 | * | if (values.output.outputAmount > remainingCostInOutputToken) { 540 | * | result.amountPaidInCollateralToken += remainingCostInOutputToken; 541 | * | values.output.outputAmount -= remainingCostInOutputToken; 542 | * | remainingCostInOutputToken = 0; 543 | | } else { 544 | * | result.amountPaidInCollateralToken += values.output.outputAmount; 545 | * | remainingCostInOutputToken -= values.output.outputAmount; 546 | * | values.output.outputAmount = 0; 547 | | } 548 | | } 549 | | 550 | * | if (remainingCostInOutputToken == 0) { return (values, result); } 551 | | 552 | * | if (values.remainingCollateralAmount > 0) { 553 | * | if (values.remainingCollateralAmount > remainingCostInOutputToken) { 554 | * | result.amountPaidInCollateralToken += remainingCostInOutputToken; 555 | * | values.remainingCollateralAmount -= remainingCostInOutputToken; 556 | * | remainingCostInOutputToken = 0; 557 | | } else { 558 | * | result.amountPaidInCollateralToken += values.remainingCollateralAmount; 559 | * | remainingCostInOutputToken -= values.remainingCollateralAmount; 560 | * | values.remainingCollateralAmount = 0; 561 | | } 562 | | } 563 | | 564 | * | if (remainingCostInOutputToken == 0) { return (values, result); } 565 | | 566 | * | Price.Props memory secondaryOutputTokenPrice = MarketUtils.getCachedTokenPrice(values.output.secondaryOutputToken, params.market, prices); 567 | | 568 | * | uint256 remainingCostInSecondaryOutputToken = remainingCostInOutputToken * collateralTokenPrice.min / secondaryOutputTokenPrice.min; 569 | | 570 | * | if (values.output.secondaryOutputAmount > 0) { 571 | | if (values.output.secondaryOutputAmount > remainingCostInSecondaryOutputToken) { 572 | | result.amountPaidInSecondaryOutputToken += remainingCostInSecondaryOutputToken; 573 | | values.output.secondaryOutputAmount -= remainingCostInSecondaryOutputToken; 574 | | remainingCostInSecondaryOutputToken = 0; 575 | | } else { 576 | | result.amountPaidInSecondaryOutputToken += values.output.secondaryOutputAmount; 577 | | remainingCostInSecondaryOutputToken -= values.output.secondaryOutputAmount; 578 | | values.output.secondaryOutputAmount = 0; 579 | | } 580 | | } 581 | | 582 | * | result.remainingCostUsd = remainingCostInSecondaryOutputToken * secondaryOutputTokenPrice.min; 583 | | 584 | * | return (values, result); 585 | | } 586 | | 587 | * | function handleEarlyReturn( 588 | | PositionUtils.UpdatePositionParams memory params, 589 | | PositionUtils.DecreasePositionCollateralValues memory values, 590 | | PositionPricingUtils.PositionFees memory fees, 591 | | ProcessCollateralCache memory collateralCache, 592 | | string memory step 593 | * | ) internal returns (PositionUtils.DecreasePositionCollateralValues memory, PositionPricingUtils.PositionFees memory) { 594 | * | if (!collateralCache.isInsolventCloseAllowed) { 595 | * | revert Errors.InsufficientFundsToPayForCosts(collateralCache.result.remainingCostUsd, step); 596 | | } 597 | | 598 | * | PositionEventUtils.emitPositionFeesInfo( 599 | * | params.contracts.eventEmitter, 600 | * | params.orderKey, 601 | * | params.positionKey, 602 | * | params.market.marketToken, 603 | * | params.position.collateralToken(), 604 | * | params.order.sizeDeltaUsd(), 605 | * | false, // isIncrease 606 | * | fees 607 | | ); 608 | | 609 | * | PositionEventUtils.emitInsolventCloseInfo( 610 | * | params.contracts.eventEmitter, 611 | * | params.orderKey, 612 | * | params.position.collateralAmount(), 613 | * | values.basePnlUsd, 614 | * | collateralCache.result.remainingCostUsd, 615 | * | step 616 | | ); 617 | | 618 | * | return (values, getEmptyFees(fees)); 619 | | } 620 | | 621 | * | function getEmptyFees( 622 | | PositionPricingUtils.PositionFees memory fees 623 | * | ) internal pure returns (PositionPricingUtils.PositionFees memory) { 624 | * | PositionPricingUtils.PositionReferralFees memory referral = PositionPricingUtils.PositionReferralFees( 625 | * | bytes32(0), // referralCode 626 | * | address(0), // affiliate 627 | * | address(0), // trader 628 | * | 0, // totalRebateFactor 629 | * | 0, // traderDiscountFactor 630 | * | 0, // totalRebateAmount 631 | * | 0, // traderDiscountAmount 632 | * | 0 // affiliateRewardAmount 633 | | ); 634 | | 635 | | // allow the accumulated funding fees to still be claimable 636 | | // return the latestFundingFeeAmountPerSize, latestLongTokenClaimableFundingAmountPerSize, 637 | | // latestShortTokenClaimableFundingAmountPerSize values as these may be used to update the 638 | | // position's values if the position will be partially closed 639 | * | PositionPricingUtils.PositionFundingFees memory funding = PositionPricingUtils.PositionFundingFees( 640 | * | 0, // fundingFeeAmount 641 | * | fees.funding.claimableLongTokenAmount, // claimableLongTokenAmount 642 | * | fees.funding.claimableShortTokenAmount, // claimableShortTokenAmount 643 | * | fees.funding.latestFundingFeeAmountPerSize, // latestFundingFeeAmountPerSize 644 | * | fees.funding.latestLongTokenClaimableFundingAmountPerSize, // latestLongTokenClaimableFundingAmountPerSize 645 | * | fees.funding.latestShortTokenClaimableFundingAmountPerSize // latestShortTokenClaimableFundingAmountPerSize 646 | | ); 647 | | 648 | * | PositionPricingUtils.PositionBorrowingFees memory borrowing = PositionPricingUtils.PositionBorrowingFees( 649 | * | 0, // borrowingFeeUsd 650 | * | 0, // borrowingFeeAmount 651 | * | 0, // borrowingFeeReceiverFactor 652 | * | 0 // borrowingFeeAmountForFeeReceiver 653 | | ); 654 | | 655 | * | PositionPricingUtils.PositionUiFees memory ui = PositionPricingUtils.PositionUiFees( 656 | * | address(0), // uiFeeReceiver 657 | * | 0, // uiFeeReceiverFactor 658 | * | 0 // uiFeeAmount 659 | | ); 660 | | 661 | | // all fees are zeroed even though funding may have been paid 662 | | // the funding fee amount value may not be accurate in the events due to this 663 | * | PositionPricingUtils.PositionFees memory _fees = PositionPricingUtils.PositionFees( 664 | * | referral, // referral 665 | * | funding, // funding 666 | * | borrowing, // borrowing 667 | * | ui, // ui 668 | * | fees.collateralTokenPrice, // collateralTokenPrice 669 | * | 0, // positionFeeFactor 670 | * | 0, // protocolFeeAmount 671 | * | 0, // positionFeeReceiverFactor 672 | * | 0, // feeReceiverAmount 673 | * | 0, // feeAmountForPool 674 | * | 0, // positionFeeAmountForPool 675 | * | 0, // positionFeeAmount 676 | * | 0, // totalCostAmountExcludingFunding 677 | * | 0 // totalCostAmount 678 | | ); 679 | | 680 | * | return _fees; 681 | | } 682 | | } 683 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionSwapUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./PositionUtils.sol"; 6 | | 7 | * | library DecreasePositionSwapUtils { 8 | | using Order for Order.Props; 9 | | using Position for Position.Props; 10 | | 11 | | // swap the withdrawn collateral from collateralToken to pnlToken if needed 12 | * | function swapWithdrawnCollateralToPnlToken( 13 | | PositionUtils.UpdatePositionParams memory params, 14 | | PositionUtils.DecreasePositionCollateralValues memory values 15 | * | ) internal returns (PositionUtils.DecreasePositionCollateralValues memory) { 16 | * | if (values.output.outputAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken) { 17 | | Market.Props[] memory swapPathMarkets = new Market.Props[](1); 18 | | swapPathMarkets[0] = params.market; 19 | | 20 | | try params.contracts.swapHandler.swap( 21 | | SwapUtils.SwapParams( 22 | | params.contracts.dataStore, 23 | | params.contracts.eventEmitter, 24 | | params.contracts.oracle, 25 | | Bank(payable(params.market.marketToken)), 26 | | params.orderKey, 27 | | params.position.collateralToken(), // tokenIn 28 | | values.output.outputAmount, // amountIn 29 | | swapPathMarkets, // markets 30 | | 0, // minOutputAmount 31 | | params.market.marketToken, // receiver 32 | | params.order.uiFeeReceiver(), // uiFeeReceiver 33 | | false // shouldUnwrapNativeToken 34 | | ) 35 | | ) returns (address tokenOut, uint256 swapOutputAmount) { 36 | | if (tokenOut != values.output.secondaryOutputToken) { 37 | | revert Errors.InvalidOutputToken(tokenOut, values.output.secondaryOutputToken); 38 | | } 39 | | // combine the values into outputToken and outputAmount 40 | | values.output.outputToken = tokenOut; 41 | | values.output.outputAmount = values.output.secondaryOutputAmount + swapOutputAmount; 42 | | values.output.secondaryOutputAmount = 0; 43 | | } catch Error(string memory reason) { 44 | | emit SwapUtils.SwapReverted(reason, ""); 45 | | } catch (bytes memory reasonBytes) { 46 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 47 | | emit SwapUtils.SwapReverted(reason, reasonBytes); 48 | | } 49 | | } 50 | | 51 | * | return values; 52 | | } 53 | | 54 | | // swap the realized profit from the pnlToken to the collateralToken if needed 55 | * | function swapProfitToCollateralToken( 56 | | PositionUtils.UpdatePositionParams memory params, 57 | | address pnlToken, 58 | | uint256 profitAmount 59 | * | ) internal returns (bool, uint256) { 60 | * | if (profitAmount > 0 && params.order.decreasePositionSwapType() == Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken) { 61 | * | Market.Props[] memory swapPathMarkets = new Market.Props[](1); 62 | * | swapPathMarkets[0] = params.market; 63 | | 64 | * | try params.contracts.swapHandler.swap( 65 | * | SwapUtils.SwapParams( 66 | * | params.contracts.dataStore, 67 | * | params.contracts.eventEmitter, 68 | * | params.contracts.oracle, 69 | * | Bank(payable(params.market.marketToken)), 70 | * | params.orderKey, 71 | * | pnlToken, // tokenIn 72 | * | profitAmount, // amountIn 73 | * | swapPathMarkets, // markets 74 | * | 0, // minOutputAmount 75 | * | params.market.marketToken, // receiver 76 | * | params.order.uiFeeReceiver(), // uiFeeReceiver 77 | * | false // shouldUnwrapNativeToken 78 | | ) 79 | | ) returns (address /* tokenOut */, uint256 swapOutputAmount) { 80 | * | return (true, swapOutputAmount); 81 | | } catch Error(string memory reason) { 82 | | emit SwapUtils.SwapReverted(reason, ""); 83 | * | } catch (bytes memory reasonBytes) { 84 | * | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(reasonBytes); 85 | * | emit SwapUtils.SwapReverted(reason, reasonBytes); 86 | | } 87 | | } 88 | | 89 | * | return (false, 0); 90 | | } 91 | | } 92 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/DecreasePositionUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/Precision.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | 10 | | import "../oracle/Oracle.sol"; 11 | | import "../pricing/PositionPricingUtils.sol"; 12 | | 13 | | import "./Position.sol"; 14 | | import "./PositionStoreUtils.sol"; 15 | | import "./PositionUtils.sol"; 16 | | import "./PositionEventUtils.sol"; 17 | | import "../order/BaseOrderUtils.sol"; 18 | | import "../order/OrderEventUtils.sol"; 19 | | 20 | | import "./DecreasePositionCollateralUtils.sol"; 21 | | 22 | | // @title DecreasePositionUtils 23 | | // @dev Library for functions to help with decreasing a position 24 | * | library DecreasePositionUtils { 25 | | using SafeCast for uint256; 26 | | using SafeCast for int256; 27 | | 28 | | using Position for Position.Props; 29 | | using Order for Order.Props; 30 | | using Price for Price.Props; 31 | | 32 | | // @dev DecreasePositionResult struct for the results of decreasePosition 33 | | // @param outputToken the output token 34 | | // @param outputAmount the output amount 35 | | // @param secondaryOutputToken the secondary output token 36 | | // @param secondaryOutputAmount the secondary output amount 37 | | struct DecreasePositionResult { 38 | | address outputToken; 39 | | uint256 outputAmount; 40 | | address secondaryOutputToken; 41 | | uint256 secondaryOutputAmount; 42 | | uint256 orderSizeDeltaUsd; 43 | | uint256 orderInitialCollateralDeltaAmount; 44 | | } 45 | | 46 | | // @dev decreases a position 47 | | // The decreasePosition function decreases the size of an existing position 48 | | // in a market. It takes a PositionUtils.UpdatePositionParams object as an input, which 49 | | // includes information about the position to be decreased, the market in 50 | | // which the position exists, and the order that is being used to decrease the position. 51 | | // 52 | | // The function first calculates the prices of the tokens in the market, and then 53 | | // checks whether the position is liquidatable based on the current market prices. 54 | | // If the order is a liquidation order and the position is not liquidatable, the function reverts. 55 | | // 56 | | // If there is not enough collateral in the position to complete the decrease, 57 | | // the function reverts. Otherwise, the function updates the position's size and 58 | | // collateral amount, and increments the claimable funding amount for 59 | | // the market if necessary. 60 | | // 61 | | // Finally, the function returns a DecreasePositionResult object containing 62 | | // information about the outcome of the decrease operation, including the amount 63 | | // of collateral removed from the position and any fees that were paid. 64 | | // @param params PositionUtils.UpdatePositionParams 65 | * | function decreasePosition( 66 | | PositionUtils.UpdatePositionParams memory params 67 | * | ) internal returns (DecreasePositionResult memory) { 68 | * | PositionUtils.DecreasePositionCache memory cache; 69 | | 70 | * | cache.prices = MarketUtils.getMarketPrices( 71 | * | params.contracts.oracle, 72 | * | params.market 73 | | ); 74 | | 75 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice( 76 | * | params.order.initialCollateralToken(), 77 | * | params.market, 78 | * | cache.prices 79 | | ); 80 | | 81 | | // cap the order size to the position size 82 | * | if (params.order.sizeDeltaUsd() > params.position.sizeInUsd()) { 83 | * | if (params.order.orderType() == Order.OrderType.LimitDecrease || 84 | * | params.order.orderType() == Order.OrderType.StopLossDecrease) { 85 | | 86 | | OrderEventUtils.emitOrderSizeDeltaAutoUpdated( 87 | | params.contracts.eventEmitter, 88 | | params.orderKey, 89 | | params.order.sizeDeltaUsd(), 90 | | params.position.sizeInUsd() 91 | | ); 92 | | 93 | | params.order.setSizeDeltaUsd(params.position.sizeInUsd()); 94 | | } else { 95 | * | revert Errors.InvalidDecreaseOrderSize(params.order.sizeDeltaUsd(), params.position.sizeInUsd()); 96 | | } 97 | | } 98 | | 99 | | // cap the initialCollateralDeltaAmount to the position collateralAmount 100 | * | if (params.order.initialCollateralDeltaAmount() > params.position.collateralAmount()) { 101 | | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated( 102 | | params.contracts.eventEmitter, 103 | | params.orderKey, 104 | | params.order.initialCollateralDeltaAmount(), 105 | | params.position.collateralAmount() 106 | | ); 107 | | 108 | | params.order.setInitialCollateralDeltaAmount(params.position.collateralAmount()); 109 | | } 110 | | 111 | | // if the position will be partially decreased then do a check on the 112 | | // remaining collateral amount and update the order attributes if needed 113 | * | if (params.order.sizeDeltaUsd() < params.position.sizeInUsd()) { 114 | | // estimate pnl based on indexTokenPrice 115 | * | (cache.estimatedPositionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd( 116 | * | params.contracts.dataStore, 117 | * | params.market, 118 | * | cache.prices, 119 | * | params.position, 120 | * | params.position.sizeInUsd() 121 | | ); 122 | | 123 | * | cache.estimatedRealizedPnlUsd = Precision.mulDiv(cache.estimatedPositionPnlUsd, params.order.sizeDeltaUsd(), params.position.sizeInUsd()); 124 | * | cache.estimatedRemainingPnlUsd = cache.estimatedPositionPnlUsd - cache.estimatedRealizedPnlUsd; 125 | | 126 | * | PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues( 127 | * | params.position.sizeInUsd() - params.order.sizeDeltaUsd(), // positionSizeInUsd 128 | * | params.position.collateralAmount() - params.order.initialCollateralDeltaAmount(), // positionCollateralAmount 129 | * | cache.estimatedRealizedPnlUsd, // realizedPnlUsd 130 | * | -params.order.sizeDeltaUsd().toInt256() // openInterestDelta 131 | | ); 132 | | 133 | * | (bool willBeSufficient, int256 estimatedRemainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient( 134 | * | params.contracts.dataStore, 135 | * | params.market, 136 | * | cache.prices, 137 | * | params.position.collateralToken(), 138 | * | params.position.isLong(), 139 | * | positionValues 140 | | ); 141 | | 142 | | // do not allow withdrawal of collateral if it would lead to the position 143 | | // having an insufficient amount of collateral 144 | | // this helps to prevent gaming by opening a position then reducing collateral 145 | | // to increase the leverage of the position 146 | * | if (!willBeSufficient) { 147 | * | if (params.order.sizeDeltaUsd() == 0) { 148 | | revert Errors.UnableToWithdrawCollateral(estimatedRemainingCollateralUsd); 149 | | } 150 | | 151 | * | OrderEventUtils.emitOrderCollateralDeltaAmountAutoUpdated( 152 | * | params.contracts.eventEmitter, 153 | * | params.orderKey, 154 | * | params.order.initialCollateralDeltaAmount(), 155 | * | 0 156 | | ); 157 | | 158 | | // the estimatedRemainingCollateralUsd subtracts the initialCollateralDeltaAmount 159 | | // since the initialCollateralDeltaAmount will be set to zero, the initialCollateralDeltaAmount 160 | | // should be added back to the estimatedRemainingCollateralUsd 161 | * | estimatedRemainingCollateralUsd += (params.order.initialCollateralDeltaAmount() * cache.collateralTokenPrice.min).toInt256(); 162 | * | params.order.setInitialCollateralDeltaAmount(0); 163 | | } 164 | | 165 | | // if the remaining collateral including position pnl will be below 166 | | // the min collateral usd value, then close the position 167 | | // 168 | | // if the position has sufficient remaining collateral including pnl 169 | | // then allow the position to be partially closed and the updated 170 | | // position to remain open 171 | * | if ((estimatedRemainingCollateralUsd + cache.estimatedRemainingPnlUsd) < params.contracts.dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256()) { 172 | * | OrderEventUtils.emitOrderSizeDeltaAutoUpdated( 173 | * | params.contracts.eventEmitter, 174 | * | params.orderKey, 175 | * | params.order.sizeDeltaUsd(), 176 | * | params.position.sizeInUsd() 177 | | ); 178 | | 179 | * | params.order.setSizeDeltaUsd(params.position.sizeInUsd()); 180 | | } 181 | | 182 | * | if ( 183 | * | params.position.sizeInUsd() > params.order.sizeDeltaUsd() && 184 | * | params.position.sizeInUsd() - params.order.sizeDeltaUsd() < params.contracts.dataStore.getUint(Keys.MIN_POSITION_SIZE_USD) 185 | | ) { 186 | | OrderEventUtils.emitOrderSizeDeltaAutoUpdated( 187 | | params.contracts.eventEmitter, 188 | | params.orderKey, 189 | | params.order.sizeDeltaUsd(), 190 | | params.position.sizeInUsd() 191 | | ); 192 | | 193 | | params.order.setSizeDeltaUsd(params.position.sizeInUsd()); 194 | | } 195 | | } 196 | | 197 | | // if the position will be closed, set the initial collateral delta amount 198 | | // to zero to help ensure that the order can be executed 199 | * | if (params.order.sizeDeltaUsd() == params.position.sizeInUsd() && params.order.initialCollateralDeltaAmount() > 0) { 200 | * | params.order.setInitialCollateralDeltaAmount(0); 201 | | } 202 | | 203 | * | cache.pnlToken = params.position.isLong() ? params.market.longToken : params.market.shortToken; 204 | * | cache.pnlTokenPrice = params.position.isLong() ? cache.prices.longTokenPrice : cache.prices.shortTokenPrice; 205 | | 206 | * | if (params.order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap && 207 | * | cache.pnlToken == params.position.collateralToken()) { 208 | * | params.order.setDecreasePositionSwapType(Order.DecreasePositionSwapType.NoSwap); 209 | | } 210 | | 211 | * | if (BaseOrderUtils.isLiquidationOrder(params.order.orderType())) { 212 | * | (bool isLiquidatable, string memory reason, PositionUtils.IsPositionLiquidatableInfo memory info) = PositionUtils.isPositionLiquidatable( 213 | * | params.contracts.dataStore, 214 | * | params.contracts.referralStorage, 215 | * | params.position, 216 | * | params.market, 217 | * | cache.prices, 218 | * | true // shouldValidateMinCollateralUsd 219 | | ); 220 | | 221 | * | if (!isLiquidatable) { 222 | | revert Errors.PositionShouldNotBeLiquidated( 223 | | reason, 224 | | info.remainingCollateralUsd, 225 | | info.minCollateralUsd, 226 | | info.minCollateralUsdForLeverage 227 | | ); 228 | | } 229 | | } 230 | | 231 | * | cache.initialCollateralAmount = params.position.collateralAmount(); 232 | * | ( 233 | * | PositionUtils.DecreasePositionCollateralValues memory values, 234 | * | PositionPricingUtils.PositionFees memory fees 235 | * | ) = DecreasePositionCollateralUtils.processCollateral( 236 | * | params, 237 | * | cache 238 | | ); 239 | | 240 | * | cache.nextPositionSizeInUsd = params.position.sizeInUsd() - params.order.sizeDeltaUsd(); 241 | * | cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor(params.contracts.dataStore, params.market.marketToken, params.position.isLong()); 242 | | 243 | * | PositionUtils.updateTotalBorrowing( 244 | * | params, 245 | * | cache.nextPositionSizeInUsd, 246 | * | cache.nextPositionBorrowingFactor 247 | | ); 248 | | 249 | * | params.position.setSizeInUsd(cache.nextPositionSizeInUsd); 250 | * | params.position.setSizeInTokens(params.position.sizeInTokens() - values.sizeDeltaInTokens); 251 | * | params.position.setCollateralAmount(values.remainingCollateralAmount); 252 | * | params.position.setDecreasedAtBlock(Chain.currentBlockNumber()); 253 | * | params.position.setDecreasedAtTime(Chain.currentTimestamp()); 254 | | 255 | * | PositionUtils.incrementClaimableFundingAmount(params, fees); 256 | | 257 | * | if (params.position.sizeInUsd() == 0 || params.position.sizeInTokens() == 0) { 258 | | // withdraw all collateral if the position will be closed 259 | * | values.output.outputAmount += params.position.collateralAmount(); 260 | | 261 | * | params.position.setSizeInUsd(0); 262 | * | params.position.setSizeInTokens(0); 263 | * | params.position.setCollateralAmount(0); 264 | | 265 | * | PositionStoreUtils.remove(params.contracts.dataStore, params.positionKey, params.order.account()); 266 | | } else { 267 | * | params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor); 268 | | 269 | * | params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize); 270 | * | params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize); 271 | * | params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize); 272 | | 273 | * | PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position); 274 | | } 275 | | 276 | * | MarketUtils.applyDeltaToCollateralSum( 277 | * | params.contracts.dataStore, 278 | * | params.contracts.eventEmitter, 279 | * | params.position.market(), 280 | * | params.position.collateralToken(), 281 | * | params.position.isLong(), 282 | * | -(cache.initialCollateralAmount - params.position.collateralAmount()).toInt256() 283 | | ); 284 | | 285 | * | PositionUtils.updateOpenInterest( 286 | * | params, 287 | * | -params.order.sizeDeltaUsd().toInt256(), 288 | * | -values.sizeDeltaInTokens.toInt256() 289 | | ); 290 | | 291 | | // affiliate rewards are still distributed even if the order is a liquidation order 292 | | // this is expected as a partial liquidation is considered the same as an automatic 293 | | // closing of a position 294 | * | PositionUtils.handleReferral(params, fees); 295 | | 296 | | // validatePosition should be called after open interest and all other market variables 297 | | // have been updated 298 | * | if (params.position.sizeInUsd() != 0 || params.position.sizeInTokens() != 0) { 299 | | // validate position which validates liquidation state is only called 300 | | // if the remaining position size is not zero 301 | | // due to this, a user can still manually close their position if 302 | | // it is in a partially liquidatable state 303 | | // this should not cause any issues as a liquidation is the same 304 | | // as automatically closing a position 305 | | // the only difference is that if the position has insufficient / negative 306 | | // collateral a liquidation transaction should still complete 307 | | // while a manual close transaction should revert 308 | * | PositionUtils.validatePosition( 309 | * | params.contracts.dataStore, 310 | * | params.contracts.referralStorage, 311 | * | params.position, 312 | * | params.market, 313 | * | cache.prices, 314 | * | false, // shouldValidateMinPositionSize 315 | * | false // shouldValidateMinCollateralUsd 316 | | ); 317 | | } 318 | | 319 | * | PositionEventUtils.emitPositionFeesCollected( 320 | * | params.contracts.eventEmitter, 321 | * | params.orderKey, 322 | * | params.positionKey, 323 | * | params.market.marketToken, 324 | * | params.position.collateralToken(), 325 | * | params.order.sizeDeltaUsd(), 326 | * | false, 327 | * | fees 328 | | ); 329 | | 330 | * | PositionEventUtils.emitPositionDecrease( 331 | * | params.contracts.eventEmitter, 332 | * | params.orderKey, 333 | * | params.positionKey, 334 | * | params.position, 335 | * | params.order.sizeDeltaUsd(), 336 | * | cache.initialCollateralAmount - params.position.collateralAmount(), 337 | * | params.order.orderType(), 338 | * | values, 339 | * | cache.prices.indexTokenPrice, 340 | * | cache.collateralTokenPrice 341 | | ); 342 | | 343 | * | values = DecreasePositionSwapUtils.swapWithdrawnCollateralToPnlToken(params, values); 344 | | 345 | * | return DecreasePositionResult( 346 | * | values.output.outputToken, 347 | * | values.output.outputAmount, 348 | * | values.output.secondaryOutputToken, 349 | * | values.output.secondaryOutputAmount, 350 | * | params.order.sizeDeltaUsd(), 351 | * | params.order.initialCollateralDeltaAmount() 352 | | ); 353 | | } 354 | | } 355 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/IncreasePositionUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/Precision.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | import "../event/EventEmitter.sol"; 9 | | 10 | | import "../oracle/Oracle.sol"; 11 | | import "../pricing/PositionPricingUtils.sol"; 12 | | 13 | | import "./Position.sol"; 14 | | import "./PositionStoreUtils.sol"; 15 | | import "./PositionUtils.sol"; 16 | | import "./PositionEventUtils.sol"; 17 | | import "../order/BaseOrderUtils.sol"; 18 | | 19 | | // @title IncreasePositionUtils 20 | | // @dev Library for functions to help with increasing a position 21 | * | library IncreasePositionUtils { 22 | | using SafeCast for uint256; 23 | | using SafeCast for int256; 24 | | 25 | | using Position for Position.Props; 26 | | using Order for Order.Props; 27 | | using Price for Price.Props; 28 | | 29 | | // @dev IncreasePositionCache struct used in increasePosition to 30 | | // avoid stack too deep errors 31 | | // @param collateralDeltaAmount the change in collateral amount 32 | | // @param executionPrice the execution price 33 | | // @param collateralTokenPrice the price of the collateral token 34 | | // @param priceImpactUsd the price impact in USD 35 | | // @param priceImpactAmount the price impact of the position increase in tokens 36 | | // @param sizeDeltaInTokens the change in position size in tokens 37 | | // @param nextPositionSizeInUsd the new position size in USD 38 | | // @param nextPositionBorrowingFactor the new position borrowing factor 39 | | struct IncreasePositionCache { 40 | | int256 collateralDeltaAmount; 41 | | uint256 executionPrice; 42 | | Price.Props collateralTokenPrice; 43 | | int256 priceImpactUsd; 44 | | int256 priceImpactAmount; 45 | | uint256 sizeDeltaInTokens; 46 | | uint256 nextPositionSizeInUsd; 47 | | uint256 nextPositionBorrowingFactor; 48 | | } 49 | | 50 | | // @dev increase a position 51 | | // The increasePosition function is used to increase the size of a position 52 | | // in a market. This involves updating the position's collateral amount, 53 | | // calculating the price impact of the size increase, and updating the position's 54 | | // size and borrowing factor. This function also applies fees to the position 55 | | // and updates the market's liquidity pool based on the new position size. 56 | | // @param params PositionUtils.UpdatePositionParams 57 | * | function increasePosition( 58 | | PositionUtils.UpdatePositionParams memory params, 59 | | uint256 collateralIncrementAmount 60 | * | ) internal { 61 | | // get the market prices for the given position 62 | * | MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices( 63 | * | params.contracts.oracle, 64 | * | params.market 65 | | ); 66 | | 67 | | // create a new cache for holding intermediate results 68 | * | IncreasePositionCache memory cache; 69 | | 70 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice( 71 | * | params.position.collateralToken(), 72 | * | params.market, 73 | * | prices 74 | | ); 75 | | 76 | * | if (params.position.sizeInUsd() == 0) { 77 | * | params.position.setFundingFeeAmountPerSize( 78 | * | MarketUtils.getFundingFeeAmountPerSize( 79 | * | params.contracts.dataStore, 80 | * | params.market.marketToken, 81 | * | params.position.collateralToken(), 82 | * | params.position.isLong() 83 | | ) 84 | | ); 85 | | 86 | * | params.position.setLongTokenClaimableFundingAmountPerSize( 87 | * | MarketUtils.getClaimableFundingAmountPerSize( 88 | * | params.contracts.dataStore, 89 | * | params.market.marketToken, 90 | * | params.market.longToken, 91 | * | params.position.isLong() 92 | | ) 93 | | ); 94 | | 95 | * | params.position.setShortTokenClaimableFundingAmountPerSize( 96 | * | MarketUtils.getClaimableFundingAmountPerSize( 97 | * | params.contracts.dataStore, 98 | * | params.market.marketToken, 99 | * | params.market.shortToken, 100 | * | params.position.isLong() 101 | | ) 102 | | ); 103 | | } 104 | | 105 | * | (cache.priceImpactUsd, cache.priceImpactAmount, cache.sizeDeltaInTokens, cache.executionPrice) = PositionUtils.getExecutionPriceForIncrease(params, prices.indexTokenPrice); 106 | | 107 | | // process the collateral for the given position and order 108 | * | PositionPricingUtils.PositionFees memory fees; 109 | * | (cache.collateralDeltaAmount, fees) = processCollateral( 110 | * | params, 111 | * | cache.collateralTokenPrice, 112 | * | collateralIncrementAmount.toInt256(), 113 | * | cache.priceImpactUsd 114 | | ); 115 | | 116 | | // check if there is sufficient collateral for the position 117 | * | if ( 118 | * | cache.collateralDeltaAmount < 0 && 119 | * | params.position.collateralAmount() < SafeCast.toUint256(-cache.collateralDeltaAmount) 120 | | ) { 121 | | revert Errors.InsufficientCollateralAmount(params.position.collateralAmount(), cache.collateralDeltaAmount); 122 | | } 123 | * | params.position.setCollateralAmount(Calc.sumReturnUint256(params.position.collateralAmount(), cache.collateralDeltaAmount)); 124 | | 125 | | // if there is a positive impact, the impact pool amount should be reduced 126 | | // if there is a negative impact, the impact pool amount should be increased 127 | * | MarketUtils.applyDeltaToPositionImpactPool( 128 | * | params.contracts.dataStore, 129 | * | params.contracts.eventEmitter, 130 | * | params.market.marketToken, 131 | * | -cache.priceImpactAmount 132 | | ); 133 | | 134 | * | cache.nextPositionSizeInUsd = params.position.sizeInUsd() + params.order.sizeDeltaUsd(); 135 | * | cache.nextPositionBorrowingFactor = MarketUtils.getCumulativeBorrowingFactor( 136 | * | params.contracts.dataStore, 137 | * | params.market.marketToken, 138 | * | params.position.isLong() 139 | | ); 140 | | 141 | * | PositionUtils.updateTotalBorrowing( 142 | * | params, 143 | * | cache.nextPositionSizeInUsd, 144 | * | cache.nextPositionBorrowingFactor 145 | | ); 146 | | 147 | * | PositionUtils.incrementClaimableFundingAmount(params, fees); 148 | | 149 | * | params.position.setSizeInUsd(cache.nextPositionSizeInUsd); 150 | * | params.position.setSizeInTokens(params.position.sizeInTokens() + cache.sizeDeltaInTokens); 151 | | 152 | * | params.position.setFundingFeeAmountPerSize(fees.funding.latestFundingFeeAmountPerSize); 153 | * | params.position.setLongTokenClaimableFundingAmountPerSize(fees.funding.latestLongTokenClaimableFundingAmountPerSize); 154 | * | params.position.setShortTokenClaimableFundingAmountPerSize(fees.funding.latestShortTokenClaimableFundingAmountPerSize); 155 | | 156 | * | params.position.setBorrowingFactor(cache.nextPositionBorrowingFactor); 157 | * | params.position.setIncreasedAtBlock(Chain.currentBlockNumber()); 158 | * | params.position.setIncreasedAtTime(Chain.currentTimestamp()); 159 | | 160 | * | PositionStoreUtils.set(params.contracts.dataStore, params.positionKey, params.position); 161 | | 162 | * | PositionUtils.updateOpenInterest( 163 | * | params, 164 | * | params.order.sizeDeltaUsd().toInt256(), 165 | * | cache.sizeDeltaInTokens.toInt256() 166 | | ); 167 | | 168 | * | if (params.order.sizeDeltaUsd() > 0) { 169 | | // reserves are only validated if the sizeDeltaUsd is more than zero 170 | | // this helps to ensure that deposits of collateral into positions 171 | | // should still succeed even if pool tokens are fully reserved 172 | * | MarketUtils.validateReserve( 173 | * | params.contracts.dataStore, 174 | * | params.market, 175 | * | prices, 176 | * | params.order.isLong() 177 | | ); 178 | | 179 | * | MarketUtils.validateOpenInterestReserve( 180 | * | params.contracts.dataStore, 181 | * | params.market, 182 | * | prices, 183 | * | params.order.isLong() 184 | | ); 185 | | 186 | * | PositionUtils.WillPositionCollateralBeSufficientValues memory positionValues = PositionUtils.WillPositionCollateralBeSufficientValues( 187 | * | params.position.sizeInUsd(), // positionSizeInUsd 188 | * | params.position.collateralAmount(), // positionCollateralAmount 189 | * | 0, // realizedPnlUsd 190 | * | 0 // openInterestDelta 191 | | ); 192 | | 193 | * | (bool willBeSufficient, int256 remainingCollateralUsd) = PositionUtils.willPositionCollateralBeSufficient( 194 | * | params.contracts.dataStore, 195 | * | params.market, 196 | * | prices, 197 | * | params.position.collateralToken(), 198 | * | params.position.isLong(), 199 | * | positionValues 200 | | ); 201 | | 202 | * | if (!willBeSufficient) { 203 | * | revert Errors.InsufficientCollateralUsd(remainingCollateralUsd); 204 | | } 205 | | } 206 | | 207 | * | PositionUtils.handleReferral(params, fees); 208 | | 209 | | // validatePosition should be called after open interest and all other market variables 210 | | // have been updated 211 | * | PositionUtils.validatePosition( 212 | * | params.contracts.dataStore, 213 | * | params.contracts.referralStorage, 214 | * | params.position, 215 | * | params.market, 216 | * | prices, 217 | * | true, // shouldValidateMinPositionSize 218 | * | true // shouldValidateMinCollateralUsd 219 | | ); 220 | | 221 | * | PositionEventUtils.emitPositionFeesCollected( 222 | * | params.contracts.eventEmitter, 223 | * | params.orderKey, 224 | * | params.positionKey, 225 | * | params.market.marketToken, 226 | * | params.position.collateralToken(), 227 | * | params.order.sizeDeltaUsd(), 228 | * | true, 229 | * | fees 230 | | ); 231 | | 232 | * | PositionEventUtils.PositionIncreaseParams memory eventParams; 233 | * | eventParams.eventEmitter = params.contracts.eventEmitter; 234 | * | eventParams.orderKey = params.orderKey; 235 | * | eventParams.positionKey = params.positionKey; 236 | * | eventParams.position = params.position; 237 | * | eventParams.indexTokenPrice = prices.indexTokenPrice; 238 | * | eventParams.executionPrice = cache.executionPrice; 239 | * | eventParams.collateralTokenPrice = cache.collateralTokenPrice; 240 | * | eventParams.sizeDeltaUsd = params.order.sizeDeltaUsd(); 241 | * | eventParams.sizeDeltaInTokens = cache.sizeDeltaInTokens; 242 | * | eventParams.collateralDeltaAmount = cache.collateralDeltaAmount; 243 | * | eventParams.priceImpactUsd = cache.priceImpactUsd; 244 | * | eventParams.priceImpactAmount = cache.priceImpactAmount; 245 | * | eventParams.orderType = params.order.orderType(); 246 | | 247 | * | PositionEventUtils.emitPositionIncrease(eventParams); 248 | | } 249 | | 250 | | // @dev handle the collateral changes of the position 251 | | // @param params PositionUtils.UpdatePositionParams 252 | | // @param prices the prices of the tokens in the market 253 | | // @param position the position to process collateral for 254 | | // @param collateralDeltaAmount the change in the position's collateral 255 | * | function processCollateral( 256 | | PositionUtils.UpdatePositionParams memory params, 257 | | Price.Props memory collateralTokenPrice, 258 | | int256 collateralDeltaAmount, 259 | | int256 priceImpactUsd 260 | * | ) internal returns (int256, PositionPricingUtils.PositionFees memory) { 261 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams( 262 | * | params.contracts.dataStore, // dataStore 263 | * | params.contracts.referralStorage, // referralStorage 264 | * | params.position, // position 265 | * | collateralTokenPrice, // collateralTokenPrice 266 | * | priceImpactUsd > 0, // forPositiveImpact 267 | * | params.market.longToken, // longToken 268 | * | params.market.shortToken, // shortToken 269 | * | params.order.sizeDeltaUsd(), // sizeDeltaUsd 270 | * | params.order.uiFeeReceiver() // uiFeeReceiver 271 | | ); 272 | | 273 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams); 274 | | 275 | * | FeeUtils.incrementClaimableFeeAmount( 276 | * | params.contracts.dataStore, 277 | * | params.contracts.eventEmitter, 278 | * | params.market.marketToken, 279 | * | params.position.collateralToken(), 280 | * | fees.feeReceiverAmount, 281 | | Keys.POSITION_FEE_TYPE 282 | | ); 283 | | 284 | * | FeeUtils.incrementClaimableUiFeeAmount( 285 | * | params.contracts.dataStore, 286 | * | params.contracts.eventEmitter, 287 | * | params.order.uiFeeReceiver(), 288 | * | params.market.marketToken, 289 | * | params.position.collateralToken(), 290 | * | fees.ui.uiFeeAmount, 291 | | Keys.UI_POSITION_FEE_TYPE 292 | | ); 293 | | 294 | * | collateralDeltaAmount -= fees.totalCostAmount.toInt256(); 295 | | 296 | * | MarketUtils.applyDeltaToCollateralSum( 297 | * | params.contracts.dataStore, 298 | * | params.contracts.eventEmitter, 299 | * | params.order.market(), 300 | * | params.position.collateralToken(), 301 | * | params.order.isLong(), 302 | * | collateralDeltaAmount 303 | | ); 304 | | 305 | * | MarketUtils.applyDeltaToPoolAmount( 306 | * | params.contracts.dataStore, 307 | * | params.contracts.eventEmitter, 308 | * | params.market, 309 | * | params.position.collateralToken(), 310 | * | fees.feeAmountForPool.toInt256() 311 | | ); 312 | | 313 | * | return (collateralDeltaAmount, fees); 314 | | } 315 | | } 316 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/Position.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title Position 6 | | // @dev Stuct for positions 7 | | // 8 | | // borrowing fees for position require only a borrowingFactor to track 9 | | // an example on how this works is if the global cumulativeBorrowingFactor is 10020% 10 | | // a position would be opened with borrowingFactor as 10020% 11 | | // after some time, if the cumulativeBorrowingFactor is updated to 10025% the position would 12 | | // owe 5% of the position size as borrowing fees 13 | | // the total pending borrowing fees of all positions is factored into the calculation of the pool value for LPs 14 | | // when a position is increased or decreased, the pending borrowing fees for the position is deducted from the position's 15 | | // collateral and transferred into the LP pool 16 | | // 17 | | // the same borrowing fee factor tracking cannot be applied for funding fees as those calculations consider pending funding fees 18 | | // based on the fiat value of the position sizes 19 | | // 20 | | // for example, if the price of the longToken is $2000 and a long position owes $200 in funding fees, the opposing short position 21 | | // claims the funding fees of 0.1 longToken ($200), if the price of the longToken changes to $4000 later, the long position would 22 | | // only owe 0.05 longToken ($200) 23 | | // this would result in differences between the amounts deducted and amounts paid out, for this reason, the actual token amounts 24 | | // to be deducted and to be paid out need to be tracked instead 25 | | // 26 | | // for funding fees, there are four values to consider: 27 | | // 1. long positions with market.longToken as collateral 28 | | // 2. long positions with market.shortToken as collateral 29 | | // 3. short positions with market.longToken as collateral 30 | | // 4. short positions with market.shortToken as collateral 31 | * | library Position { 32 | | // @dev there is a limit on the number of fields a struct can have when being passed 33 | | // or returned as a memory variable which can cause "Stack too deep" errors 34 | | // use sub-structs to avoid this issue 35 | | // @param addresses address values 36 | | // @param numbers number values 37 | | // @param flags boolean values 38 | | struct Props { 39 | | Addresses addresses; 40 | | Numbers numbers; 41 | | Flags flags; 42 | | } 43 | | 44 | | // @param account the position's account 45 | | // @param market the position's market 46 | | // @param collateralToken the position's collateralToken 47 | | struct Addresses { 48 | | address account; 49 | | address market; 50 | | address collateralToken; 51 | | } 52 | | 53 | | // @param sizeInUsd the position's size in USD 54 | | // @param sizeInTokens the position's size in tokens 55 | | // @param collateralAmount the amount of collateralToken for collateral 56 | | // @param borrowingFactor the position's borrowing factor 57 | | // @param fundingFeeAmountPerSize the position's funding fee per size 58 | | // @param longTokenClaimableFundingAmountPerSize the position's claimable funding amount per size 59 | | // for the market.longToken 60 | | // @param shortTokenClaimableFundingAmountPerSize the position's claimable funding amount per size 61 | | // for the market.shortToken 62 | | // @param increasedAtBlock the block at which the position was last increased 63 | | // @param decreasedAtBlock the block at which the position was last decreased 64 | | struct Numbers { 65 | | uint256 sizeInUsd; 66 | | uint256 sizeInTokens; 67 | | uint256 collateralAmount; 68 | | uint256 borrowingFactor; 69 | | uint256 fundingFeeAmountPerSize; 70 | | uint256 longTokenClaimableFundingAmountPerSize; 71 | | uint256 shortTokenClaimableFundingAmountPerSize; 72 | | uint256 increasedAtBlock; 73 | | uint256 decreasedAtBlock; 74 | | uint256 increasedAtTime; 75 | | uint256 decreasedAtTime; 76 | | } 77 | | 78 | | // @param isLong whether the position is a long or short 79 | | struct Flags { 80 | | bool isLong; 81 | | } 82 | | 83 | * | function account(Props memory props) internal pure returns (address) { 84 | * | return props.addresses.account; 85 | | } 86 | | 87 | * | function setAccount(Props memory props, address value) internal pure { 88 | * | props.addresses.account = value; 89 | | } 90 | | 91 | * | function market(Props memory props) internal pure returns (address) { 92 | * | return props.addresses.market; 93 | | } 94 | | 95 | * | function setMarket(Props memory props, address value) internal pure { 96 | * | props.addresses.market = value; 97 | | } 98 | | 99 | * | function collateralToken(Props memory props) internal pure returns (address) { 100 | * | return props.addresses.collateralToken; 101 | | } 102 | | 103 | * | function setCollateralToken(Props memory props, address value) internal pure { 104 | * | props.addresses.collateralToken = value; 105 | | } 106 | | 107 | * | function sizeInUsd(Props memory props) internal pure returns (uint256) { 108 | * | return props.numbers.sizeInUsd; 109 | | } 110 | | 111 | * | function setSizeInUsd(Props memory props, uint256 value) internal pure { 112 | * | props.numbers.sizeInUsd = value; 113 | | } 114 | | 115 | * | function sizeInTokens(Props memory props) internal pure returns (uint256) { 116 | * | return props.numbers.sizeInTokens; 117 | | } 118 | | 119 | * | function setSizeInTokens(Props memory props, uint256 value) internal pure { 120 | * | props.numbers.sizeInTokens = value; 121 | | } 122 | | 123 | * | function collateralAmount(Props memory props) internal pure returns (uint256) { 124 | * | return props.numbers.collateralAmount; 125 | | } 126 | | 127 | * | function setCollateralAmount(Props memory props, uint256 value) internal pure { 128 | * | props.numbers.collateralAmount = value; 129 | | } 130 | | 131 | * | function borrowingFactor(Props memory props) internal pure returns (uint256) { 132 | * | return props.numbers.borrowingFactor; 133 | | } 134 | | 135 | * | function setBorrowingFactor(Props memory props, uint256 value) internal pure { 136 | * | props.numbers.borrowingFactor = value; 137 | | } 138 | | 139 | * | function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) { 140 | * | return props.numbers.fundingFeeAmountPerSize; 141 | | } 142 | | 143 | * | function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure { 144 | * | props.numbers.fundingFeeAmountPerSize = value; 145 | | } 146 | | 147 | * | function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) { 148 | * | return props.numbers.longTokenClaimableFundingAmountPerSize; 149 | | } 150 | | 151 | * | function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure { 152 | * | props.numbers.longTokenClaimableFundingAmountPerSize = value; 153 | | } 154 | | 155 | * | function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) { 156 | * | return props.numbers.shortTokenClaimableFundingAmountPerSize; 157 | | } 158 | | 159 | * | function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure { 160 | * | props.numbers.shortTokenClaimableFundingAmountPerSize = value; 161 | | } 162 | | 163 | * | function increasedAtBlock(Props memory props) internal pure returns (uint256) { 164 | * | return props.numbers.increasedAtBlock; 165 | | } 166 | | 167 | * | function setIncreasedAtBlock(Props memory props, uint256 value) internal pure { 168 | * | props.numbers.increasedAtBlock = value; 169 | | } 170 | | 171 | * | function decreasedAtBlock(Props memory props) internal pure returns (uint256) { 172 | * | return props.numbers.decreasedAtBlock; 173 | | } 174 | | 175 | * | function setDecreasedAtBlock(Props memory props, uint256 value) internal pure { 176 | * | props.numbers.decreasedAtBlock = value; 177 | | } 178 | | 179 | * | function increasedAtTime(Props memory props) internal pure returns (uint256) { 180 | * | return props.numbers.increasedAtTime; 181 | | } 182 | | 183 | * | function setIncreasedAtTime(Props memory props, uint256 value) internal pure { 184 | * | props.numbers.increasedAtTime = value; 185 | | } 186 | | 187 | * | function decreasedAtTime(Props memory props) internal pure returns (uint256) { 188 | * | return props.numbers.decreasedAtTime; 189 | | } 190 | | 191 | * | function setDecreasedAtTime(Props memory props, uint256 value) internal pure { 192 | * | props.numbers.decreasedAtTime = value; 193 | | } 194 | | 195 | * | function isLong(Props memory props) internal pure returns (bool) { 196 | * | return props.flags.isLong; 197 | | } 198 | | 199 | * | function setIsLong(Props memory props, bool value) internal pure { 200 | * | props.flags.isLong = value; 201 | | } 202 | | 203 | | // @dev get the key for a position 204 | | // @param account the position's account 205 | | // @param market the position's market 206 | | // @param collateralToken the position's collateralToken 207 | | // @param isLong whether the position is long or short 208 | | // @return the position key 209 | * | function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) { 210 | * | bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong)); 211 | * | return _key; 212 | | } 213 | | } 214 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./Position.sol"; 10 | | import "./PositionUtils.sol"; 11 | | import "../pricing/PositionPricingUtils.sol"; 12 | | 13 | * | library PositionEventUtils { 14 | | using Position for Position.Props; 15 | | 16 | | using EventUtils for EventUtils.AddressItems; 17 | | using EventUtils for EventUtils.UintItems; 18 | | using EventUtils for EventUtils.IntItems; 19 | | using EventUtils for EventUtils.BoolItems; 20 | | using EventUtils for EventUtils.Bytes32Items; 21 | | using EventUtils for EventUtils.BytesItems; 22 | | using EventUtils for EventUtils.StringItems; 23 | | 24 | | struct PositionIncreaseParams { 25 | | EventEmitter eventEmitter; 26 | | bytes32 orderKey; 27 | | bytes32 positionKey; 28 | | Position.Props position; 29 | | Price.Props indexTokenPrice; 30 | | Price.Props collateralTokenPrice; 31 | | uint256 executionPrice; 32 | | uint256 sizeDeltaUsd; 33 | | uint256 sizeDeltaInTokens; 34 | | int256 collateralDeltaAmount; 35 | | int256 priceImpactUsd; 36 | | int256 priceImpactAmount; 37 | | Order.OrderType orderType; 38 | | } 39 | | 40 | * | function emitPositionIncrease(PositionIncreaseParams memory params) internal { 41 | * | EventUtils.EventLogData memory eventData; 42 | | 43 | * | eventData.addressItems.initItems(3); 44 | * | eventData.addressItems.setItem(0, "account", params.position.account()); 45 | * | eventData.addressItems.setItem(1, "market", params.position.market()); 46 | * | eventData.addressItems.setItem(2, "collateralToken", params.position.collateralToken()); 47 | | 48 | * | eventData.uintItems.initItems(16); 49 | * | eventData.uintItems.setItem(0, "sizeInUsd", params.position.sizeInUsd()); 50 | * | eventData.uintItems.setItem(1, "sizeInTokens", params.position.sizeInTokens()); 51 | * | eventData.uintItems.setItem(2, "collateralAmount", params.position.collateralAmount()); 52 | * | eventData.uintItems.setItem(3, "borrowingFactor", params.position.borrowingFactor()); 53 | * | eventData.uintItems.setItem(4, "fundingFeeAmountPerSize", params.position.fundingFeeAmountPerSize()); 54 | * | eventData.uintItems.setItem(5, "longTokenClaimableFundingAmountPerSize", params.position.longTokenClaimableFundingAmountPerSize()); 55 | * | eventData.uintItems.setItem(6, "shortTokenClaimableFundingAmountPerSize", params.position.shortTokenClaimableFundingAmountPerSize()); 56 | * | eventData.uintItems.setItem(7, "executionPrice", params.executionPrice); 57 | * | eventData.uintItems.setItem(8, "indexTokenPrice.max", params.indexTokenPrice.max); 58 | * | eventData.uintItems.setItem(9, "indexTokenPrice.min", params.indexTokenPrice.min); 59 | * | eventData.uintItems.setItem(10, "collateralTokenPrice.max", params.collateralTokenPrice.max); 60 | * | eventData.uintItems.setItem(11, "collateralTokenPrice.min", params.collateralTokenPrice.min); 61 | * | eventData.uintItems.setItem(12, "sizeDeltaUsd", params.sizeDeltaUsd); 62 | * | eventData.uintItems.setItem(13, "sizeDeltaInTokens", params.sizeDeltaInTokens); 63 | * | eventData.uintItems.setItem(14, "orderType", uint256(params.orderType)); 64 | * | eventData.uintItems.setItem(15, "increasedAtTime", uint256(params.position.increasedAtTime())); 65 | | 66 | * | eventData.intItems.initItems(3); 67 | * | eventData.intItems.setItem(0, "collateralDeltaAmount", params.collateralDeltaAmount); 68 | * | eventData.intItems.setItem(1, "priceImpactUsd", params.priceImpactUsd); 69 | * | eventData.intItems.setItem(2, "priceImpactAmount", params.priceImpactAmount); 70 | | 71 | * | eventData.boolItems.initItems(1); 72 | * | eventData.boolItems.setItem(0, "isLong", params.position.isLong()); 73 | | 74 | * | eventData.bytes32Items.initItems(2); 75 | * | eventData.bytes32Items.setItem(0, "orderKey", params.orderKey); 76 | * | eventData.bytes32Items.setItem(1, "positionKey", params.positionKey); 77 | | 78 | * | params.eventEmitter.emitEventLog1( 79 | | "PositionIncrease", 80 | * | Cast.toBytes32(params.position.account()), 81 | * | eventData 82 | | ); 83 | | } 84 | | 85 | * | function emitPositionDecrease( 86 | | EventEmitter eventEmitter, 87 | | bytes32 orderKey, 88 | | bytes32 positionKey, 89 | | Position.Props memory position, 90 | | uint256 sizeDeltaUsd, 91 | | uint256 collateralDeltaAmount, 92 | | Order.OrderType orderType, 93 | | PositionUtils.DecreasePositionCollateralValues memory values, 94 | | Price.Props memory indexTokenPrice, 95 | | Price.Props memory collateralTokenPrice 96 | * | ) internal { 97 | * | EventUtils.EventLogData memory eventData; 98 | | 99 | * | eventData.addressItems.initItems(3); 100 | * | eventData.addressItems.setItem(0, "account", position.account()); 101 | * | eventData.addressItems.setItem(1, "market", position.market()); 102 | * | eventData.addressItems.setItem(2, "collateralToken", position.collateralToken()); 103 | | 104 | * | eventData.uintItems.initItems(18); 105 | * | eventData.uintItems.setItem(0, "sizeInUsd", position.sizeInUsd()); 106 | * | eventData.uintItems.setItem(1, "sizeInTokens", position.sizeInTokens()); 107 | * | eventData.uintItems.setItem(2, "collateralAmount", position.collateralAmount()); 108 | * | eventData.uintItems.setItem(3, "borrowingFactor", position.borrowingFactor()); 109 | * | eventData.uintItems.setItem(4, "fundingFeeAmountPerSize", position.fundingFeeAmountPerSize()); 110 | * | eventData.uintItems.setItem(5, "longTokenClaimableFundingAmountPerSize", position.longTokenClaimableFundingAmountPerSize()); 111 | * | eventData.uintItems.setItem(6, "shortTokenClaimableFundingAmountPerSize", position.shortTokenClaimableFundingAmountPerSize()); 112 | * | eventData.uintItems.setItem(7, "executionPrice", values.executionPrice); 113 | * | eventData.uintItems.setItem(8, "indexTokenPrice.max", indexTokenPrice.max); 114 | * | eventData.uintItems.setItem(9, "indexTokenPrice.min", indexTokenPrice.min); 115 | * | eventData.uintItems.setItem(10, "collateralTokenPrice.max", collateralTokenPrice.max); 116 | * | eventData.uintItems.setItem(11, "collateralTokenPrice.min", collateralTokenPrice.min); 117 | * | eventData.uintItems.setItem(12, "sizeDeltaUsd", sizeDeltaUsd); 118 | * | eventData.uintItems.setItem(13, "sizeDeltaInTokens", values.sizeDeltaInTokens); 119 | * | eventData.uintItems.setItem(14, "collateralDeltaAmount", collateralDeltaAmount); 120 | * | eventData.uintItems.setItem(15, "values.priceImpactDiffUsd", values.priceImpactDiffUsd); 121 | * | eventData.uintItems.setItem(16, "orderType", uint256(orderType)); 122 | * | eventData.uintItems.setItem(17, "decreasedAtTime", position.decreasedAtTime()); 123 | | 124 | * | eventData.intItems.initItems(3); 125 | * | eventData.intItems.setItem(0, "priceImpactUsd", values.priceImpactUsd); 126 | * | eventData.intItems.setItem(1, "basePnlUsd", values.basePnlUsd); 127 | * | eventData.intItems.setItem(2, "uncappedBasePnlUsd", values.uncappedBasePnlUsd); 128 | | 129 | * | eventData.boolItems.initItems(1); 130 | * | eventData.boolItems.setItem(0, "isLong", position.isLong()); 131 | | 132 | * | eventData.bytes32Items.initItems(2); 133 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey); 134 | * | eventData.bytes32Items.setItem(1, "positionKey", positionKey); 135 | | 136 | * | eventEmitter.emitEventLog1( 137 | | "PositionDecrease", 138 | * | Cast.toBytes32(position.account()), 139 | * | eventData 140 | | ); 141 | | } 142 | | 143 | * | function emitInsolventCloseInfo( 144 | | EventEmitter eventEmitter, 145 | | bytes32 orderKey, 146 | | uint256 positionCollateralAmount, 147 | | int256 basePnlUsd, 148 | | uint256 remainingCostUsd, 149 | | string memory step 150 | * | ) internal { 151 | * | EventUtils.EventLogData memory eventData; 152 | | 153 | * | eventData.bytes32Items.initItems(1); 154 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey); 155 | | 156 | * | eventData.uintItems.initItems(2); 157 | * | eventData.uintItems.setItem(0, "positionCollateralAmount", positionCollateralAmount); 158 | * | eventData.uintItems.setItem(1, "remainingCostUsd", remainingCostUsd); 159 | | 160 | * | eventData.intItems.initItems(1); 161 | * | eventData.intItems.setItem(0, "basePnlUsd", basePnlUsd); 162 | | 163 | * | eventData.stringItems.initItems(1); 164 | * | eventData.stringItems.setItem(0, "step", step); 165 | | 166 | * | eventEmitter.emitEventLog( 167 | | "InsolventClose", 168 | * | eventData 169 | | ); 170 | | } 171 | | 172 | * | function emitInsufficientFundingFeePayment( 173 | | EventEmitter eventEmitter, 174 | | address market, 175 | | address token, 176 | | uint256 expectedAmount, 177 | | uint256 amountPaidInCollateralToken, 178 | | uint256 amountPaidInSecondaryOutputToken 179 | * | ) internal { 180 | * | EventUtils.EventLogData memory eventData; 181 | | 182 | * | eventData.addressItems.initItems(2); 183 | * | eventData.addressItems.setItem(0, "market", market); 184 | * | eventData.addressItems.setItem(1, "token", token); 185 | | 186 | * | eventData.uintItems.initItems(3); 187 | * | eventData.uintItems.setItem(0, "expectedAmount", expectedAmount); 188 | * | eventData.uintItems.setItem(1, "amountPaidInCollateralToken", amountPaidInCollateralToken); 189 | * | eventData.uintItems.setItem(2, "amountPaidInSecondaryOutputToken", amountPaidInSecondaryOutputToken); 190 | | 191 | * | eventEmitter.emitEventLog1( 192 | | "InsufficientFundingFeePayment", 193 | * | Cast.toBytes32(market), 194 | * | eventData 195 | | ); 196 | | } 197 | | 198 | * | function emitPositionFeesCollected( 199 | | EventEmitter eventEmitter, 200 | | bytes32 orderKey, 201 | | bytes32 positionKey, 202 | | address market, 203 | | address collateralToken, 204 | | uint256 tradeSizeUsd, 205 | | bool isIncrease, 206 | | PositionPricingUtils.PositionFees memory fees 207 | | ) internal { 208 | * | _emitPositionFees( 209 | * | eventEmitter, 210 | * | orderKey, 211 | * | positionKey, 212 | * | market, 213 | * | collateralToken, 214 | * | tradeSizeUsd, 215 | * | isIncrease, 216 | * | fees, 217 | | "PositionFeesCollected" 218 | | ); 219 | | } 220 | | 221 | * | function emitPositionFeesInfo( 222 | | EventEmitter eventEmitter, 223 | | bytes32 orderKey, 224 | | bytes32 positionKey, 225 | | address market, 226 | | address collateralToken, 227 | | uint256 tradeSizeUsd, 228 | | bool isIncrease, 229 | | PositionPricingUtils.PositionFees memory fees 230 | | ) internal { 231 | * | _emitPositionFees( 232 | * | eventEmitter, 233 | * | orderKey, 234 | * | positionKey, 235 | * | market, 236 | * | collateralToken, 237 | * | tradeSizeUsd, 238 | * | isIncrease, 239 | * | fees, 240 | | "PositionFeesInfo" 241 | | ); 242 | | } 243 | | 244 | * | function _emitPositionFees( 245 | | EventEmitter eventEmitter, 246 | | bytes32 orderKey, 247 | | bytes32 positionKey, 248 | | address market, 249 | | address collateralToken, 250 | | uint256 tradeSizeUsd, 251 | | bool isIncrease, 252 | | PositionPricingUtils.PositionFees memory fees, 253 | | string memory eventName 254 | * | ) internal { 255 | * | EventUtils.EventLogData memory eventData; 256 | | 257 | * | eventData.bytes32Items.initItems(3); 258 | * | eventData.bytes32Items.setItem(0, "orderKey", orderKey); 259 | * | eventData.bytes32Items.setItem(1, "positionKey", positionKey); 260 | * | eventData.bytes32Items.setItem(2, "referralCode", fees.referral.referralCode); 261 | | 262 | * | eventData.addressItems.initItems(5); 263 | * | eventData.addressItems.setItem(0, "market", market); 264 | * | eventData.addressItems.setItem(1, "collateralToken", collateralToken); 265 | * | eventData.addressItems.setItem(2, "affiliate", fees.referral.affiliate); 266 | * | eventData.addressItems.setItem(3, "trader", fees.referral.trader); 267 | * | eventData.addressItems.setItem(4, "uiFeeReceiver", fees.ui.uiFeeReceiver); 268 | | 269 | | // in case the position was insolvent, the fundingFeeAmount and feeAmountForPool 270 | | // values may not be accurate 271 | * | eventData.uintItems.initItems(28); 272 | * | eventData.uintItems.setItem(0, "collateralTokenPrice.min", fees.collateralTokenPrice.min); 273 | * | eventData.uintItems.setItem(1, "collateralTokenPrice.max", fees.collateralTokenPrice.max); 274 | * | eventData.uintItems.setItem(2, "tradeSizeUsd", tradeSizeUsd); 275 | * | eventData.uintItems.setItem(3, "totalRebateFactor", fees.referral.totalRebateFactor); 276 | * | eventData.uintItems.setItem(4, "traderDiscountFactor", fees.referral.traderDiscountFactor); 277 | * | eventData.uintItems.setItem(5, "totalRebateAmount", fees.referral.totalRebateAmount); 278 | * | eventData.uintItems.setItem(6, "traderDiscountAmount", fees.referral.traderDiscountAmount); 279 | * | eventData.uintItems.setItem(7, "affiliateRewardAmount", fees.referral.affiliateRewardAmount); 280 | * | eventData.uintItems.setItem(8, "fundingFeeAmount", fees.funding.fundingFeeAmount); 281 | * | eventData.uintItems.setItem(9, "claimableLongTokenAmount", fees.funding.claimableLongTokenAmount); 282 | * | eventData.uintItems.setItem(10, "claimableShortTokenAmount", fees.funding.claimableShortTokenAmount); 283 | * | eventData.uintItems.setItem(11, "latestFundingFeeAmountPerSize", fees.funding.latestFundingFeeAmountPerSize); 284 | * | eventData.uintItems.setItem(12, "latestLongTokenClaimableFundingAmountPerSize", fees.funding.latestLongTokenClaimableFundingAmountPerSize); 285 | * | eventData.uintItems.setItem(13, "latestShortTokenClaimableFundingAmountPerSize", fees.funding.latestShortTokenClaimableFundingAmountPerSize); 286 | * | eventData.uintItems.setItem(14, "borrowingFeeUsd", fees.borrowing.borrowingFeeUsd); 287 | * | eventData.uintItems.setItem(15, "borrowingFeeAmount", fees.borrowing.borrowingFeeAmount); 288 | * | eventData.uintItems.setItem(16, "borrowingFeeReceiverFactor", fees.borrowing.borrowingFeeReceiverFactor); 289 | * | eventData.uintItems.setItem(17, "borrowingFeeAmountForFeeReceiver", fees.borrowing.borrowingFeeAmountForFeeReceiver); 290 | * | eventData.uintItems.setItem(18, "positionFeeFactor", fees.positionFeeFactor); 291 | * | eventData.uintItems.setItem(19, "protocolFeeAmount", fees.protocolFeeAmount); 292 | * | eventData.uintItems.setItem(20, "positionFeeReceiverFactor", fees.positionFeeReceiverFactor); 293 | * | eventData.uintItems.setItem(21, "feeReceiverAmount", fees.feeReceiverAmount); 294 | * | eventData.uintItems.setItem(22, "feeAmountForPool", fees.feeAmountForPool); 295 | * | eventData.uintItems.setItem(23, "positionFeeAmountForPool", fees.positionFeeAmountForPool); 296 | * | eventData.uintItems.setItem(24, "positionFeeAmount", fees.positionFeeAmount); 297 | * | eventData.uintItems.setItem(25, "totalCostAmount", fees.totalCostAmount); 298 | * | eventData.uintItems.setItem(26, "uiFeeReceiverFactor", fees.ui.uiFeeReceiverFactor); 299 | * | eventData.uintItems.setItem(27, "uiFeeAmount", fees.ui.uiFeeAmount); 300 | | 301 | * | eventData.boolItems.initItems(1); 302 | * | eventData.boolItems.setItem(0, "isIncrease", isIncrease); 303 | | 304 | * | eventEmitter.emitEventLog1( 305 | * | eventName, 306 | * | Cast.toBytes32(market), 307 | * | eventData 308 | | ); 309 | | } 310 | | } 311 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Position.sol"; 9 | | 10 | | /** 11 | | * @title PositionStoreUtils 12 | | * @dev Library for position storage functions 13 | | */ 14 | * | library PositionStoreUtils { 15 | | using Position for Position.Props; 16 | | 17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 18 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET")); 19 | * | bytes32 internal constant COLLATERAL_TOKEN = keccak256(abi.encode("COLLATERAL_TOKEN")); 20 | | 21 | * | bytes32 internal constant SIZE_IN_USD = keccak256(abi.encode("SIZE_IN_USD")); 22 | * | bytes32 internal constant SIZE_IN_TOKENS = keccak256(abi.encode("SIZE_IN_TOKENS")); 23 | * | bytes32 internal constant COLLATERAL_AMOUNT = keccak256(abi.encode("COLLATERAL_AMOUNT")); 24 | * | bytes32 internal constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR")); 25 | * | bytes32 internal constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE")); 26 | * | bytes32 internal constant LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE")); 27 | * | bytes32 internal constant SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE")); 28 | * | bytes32 internal constant INCREASED_AT_BLOCK = keccak256(abi.encode("INCREASED_AT_BLOCK")); 29 | * | bytes32 internal constant DECREASED_AT_BLOCK = keccak256(abi.encode("DECREASED_AT_BLOCK")); 30 | * | bytes32 internal constant INCREASED_AT_TIME = keccak256(abi.encode("INCREASED_AT_TIME")); 31 | * | bytes32 internal constant DECREASED_AT_TIME = keccak256(abi.encode("DECREASED_AT_TIME")); 32 | | 33 | * | bytes32 internal constant IS_LONG = keccak256(abi.encode("IS_LONG")); 34 | | 35 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Position.Props memory) { 36 | * | Position.Props memory position; 37 | * | if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) { 38 | * | return position; 39 | | } 40 | | 41 | * | position.setAccount(dataStore.getAddress( 42 | * | keccak256(abi.encode(key, ACCOUNT)) 43 | | )); 44 | | 45 | * | position.setMarket(dataStore.getAddress( 46 | * | keccak256(abi.encode(key, MARKET)) 47 | | )); 48 | | 49 | * | position.setCollateralToken(dataStore.getAddress( 50 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN)) 51 | | )); 52 | | 53 | * | position.setSizeInUsd(dataStore.getUint( 54 | * | keccak256(abi.encode(key, SIZE_IN_USD)) 55 | | )); 56 | | 57 | * | position.setSizeInTokens(dataStore.getUint( 58 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS)) 59 | | )); 60 | | 61 | * | position.setCollateralAmount(dataStore.getUint( 62 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT)) 63 | | )); 64 | | 65 | * | position.setBorrowingFactor(dataStore.getUint( 66 | * | keccak256(abi.encode(key, BORROWING_FACTOR)) 67 | | )); 68 | | 69 | * | position.setFundingFeeAmountPerSize(dataStore.getUint( 70 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)) 71 | | )); 72 | | 73 | * | position.setLongTokenClaimableFundingAmountPerSize(dataStore.getUint( 74 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)) 75 | | )); 76 | | 77 | * | position.setShortTokenClaimableFundingAmountPerSize(dataStore.getUint( 78 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)) 79 | | )); 80 | | 81 | * | position.setIncreasedAtBlock(dataStore.getUint( 82 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK)) 83 | | )); 84 | | 85 | * | position.setDecreasedAtBlock(dataStore.getUint( 86 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK)) 87 | | )); 88 | | 89 | * | position.setIncreasedAtTime(dataStore.getUint( 90 | * | keccak256(abi.encode(key, INCREASED_AT_TIME)) 91 | | )); 92 | | 93 | * | position.setDecreasedAtTime(dataStore.getUint( 94 | * | keccak256(abi.encode(key, DECREASED_AT_TIME)) 95 | | )); 96 | | 97 | * | position.setIsLong(dataStore.getBool( 98 | * | keccak256(abi.encode(key, IS_LONG)) 99 | | )); 100 | | 101 | * | return position; 102 | | } 103 | | 104 | * | function set(DataStore dataStore, bytes32 key, Position.Props memory position) internal { 105 | * | dataStore.addBytes32( 106 | | Keys.POSITION_LIST, 107 | * | key 108 | | ); 109 | | 110 | * | dataStore.addBytes32( 111 | * | Keys.accountPositionListKey(position.account()), 112 | * | key 113 | | ); 114 | | 115 | * | dataStore.setAddress( 116 | * | keccak256(abi.encode(key, ACCOUNT)), 117 | * | position.account() 118 | | ); 119 | | 120 | * | dataStore.setAddress( 121 | * | keccak256(abi.encode(key, MARKET)), 122 | * | position.market() 123 | | ); 124 | | 125 | * | dataStore.setAddress( 126 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN)), 127 | * | position.collateralToken() 128 | | ); 129 | | 130 | * | dataStore.setUint( 131 | * | keccak256(abi.encode(key, SIZE_IN_USD)), 132 | * | position.sizeInUsd() 133 | | ); 134 | | 135 | * | dataStore.setUint( 136 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS)), 137 | * | position.sizeInTokens() 138 | | ); 139 | | 140 | * | dataStore.setUint( 141 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT)), 142 | * | position.collateralAmount() 143 | | ); 144 | | 145 | * | dataStore.setUint( 146 | * | keccak256(abi.encode(key, BORROWING_FACTOR)), 147 | * | position.borrowingFactor() 148 | | ); 149 | | 150 | * | dataStore.setUint( 151 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)), 152 | * | position.fundingFeeAmountPerSize() 153 | | ); 154 | | 155 | * | dataStore.setUint( 156 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)), 157 | * | position.longTokenClaimableFundingAmountPerSize() 158 | | ); 159 | | 160 | * | dataStore.setUint( 161 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)), 162 | * | position.shortTokenClaimableFundingAmountPerSize() 163 | | ); 164 | | 165 | * | dataStore.setUint( 166 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK)), 167 | * | position.increasedAtBlock() 168 | | ); 169 | | 170 | * | dataStore.setUint( 171 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK)), 172 | * | position.decreasedAtBlock() 173 | | ); 174 | | 175 | * | dataStore.setUint( 176 | * | keccak256(abi.encode(key, INCREASED_AT_TIME)), 177 | * | position.increasedAtTime() 178 | | ); 179 | | 180 | * | dataStore.setUint( 181 | * | keccak256(abi.encode(key, DECREASED_AT_TIME)), 182 | * | position.decreasedAtTime() 183 | | ); 184 | | 185 | * | dataStore.setBool( 186 | * | keccak256(abi.encode(key, IS_LONG)), 187 | * | position.isLong() 188 | | ); 189 | | } 190 | | 191 | * | function remove(DataStore dataStore, bytes32 key, address account) internal { 192 | * | if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) { 193 | | revert Errors.PositionNotFound(key); 194 | | } 195 | | 196 | * | dataStore.removeBytes32( 197 | | Keys.POSITION_LIST, 198 | * | key 199 | | ); 200 | | 201 | * | dataStore.removeBytes32( 202 | * | Keys.accountPositionListKey(account), 203 | * | key 204 | | ); 205 | | 206 | * | dataStore.removeAddress( 207 | * | keccak256(abi.encode(key, ACCOUNT)) 208 | | ); 209 | | 210 | * | dataStore.removeAddress( 211 | * | keccak256(abi.encode(key, MARKET)) 212 | | ); 213 | | 214 | * | dataStore.removeAddress( 215 | * | keccak256(abi.encode(key, COLLATERAL_TOKEN)) 216 | | ); 217 | | 218 | * | dataStore.removeUint( 219 | * | keccak256(abi.encode(key, SIZE_IN_USD)) 220 | | ); 221 | | 222 | * | dataStore.removeUint( 223 | * | keccak256(abi.encode(key, SIZE_IN_TOKENS)) 224 | | ); 225 | | 226 | * | dataStore.removeUint( 227 | * | keccak256(abi.encode(key, COLLATERAL_AMOUNT)) 228 | | ); 229 | | 230 | * | dataStore.removeUint( 231 | * | keccak256(abi.encode(key, BORROWING_FACTOR)) 232 | | ); 233 | | 234 | * | dataStore.removeUint( 235 | * | keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)) 236 | | ); 237 | | 238 | * | dataStore.removeUint( 239 | * | keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)) 240 | | ); 241 | | 242 | * | dataStore.removeUint( 243 | * | keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)) 244 | | ); 245 | | 246 | * | dataStore.removeUint( 247 | * | keccak256(abi.encode(key, INCREASED_AT_BLOCK)) 248 | | ); 249 | | 250 | * | dataStore.removeUint( 251 | * | keccak256(abi.encode(key, DECREASED_AT_BLOCK)) 252 | | ); 253 | | 254 | * | dataStore.removeUint( 255 | * | keccak256(abi.encode(key, INCREASED_AT_TIME)) 256 | | ); 257 | | 258 | * | dataStore.removeUint( 259 | * | keccak256(abi.encode(key, DECREASED_AT_TIME)) 260 | | ); 261 | | 262 | * | dataStore.removeBool( 263 | * | keccak256(abi.encode(key, IS_LONG)) 264 | | ); 265 | | } 266 | | 267 | * | function getPositionCount(DataStore dataStore) internal view returns (uint256) { 268 | * | return dataStore.getBytes32Count(Keys.POSITION_LIST); 269 | | } 270 | | 271 | | function getPositionKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 272 | | return dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end); 273 | | } 274 | | 275 | | function getAccountPositionCount(DataStore dataStore, address account) internal view returns (uint256) { 276 | | return dataStore.getBytes32Count(Keys.accountPositionListKey(account)); 277 | | } 278 | | 279 | * | function getAccountPositionKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 280 | * | return dataStore.getBytes32ValuesAt(Keys.accountPositionListKey(account), start, end); 281 | | } 282 | | } 283 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/position/PositionUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 6 | | 7 | | import "../utils/Precision.sol"; 8 | | 9 | | import "./Position.sol"; 10 | | 11 | | import "../data/DataStore.sol"; 12 | | import "../data/Keys.sol"; 13 | | 14 | | import "../pricing/PositionPricingUtils.sol"; 15 | | import "../order/BaseOrderUtils.sol"; 16 | | 17 | | // @title PositionUtils 18 | | // @dev Library for position functions 19 | * | library PositionUtils { 20 | | using SafeCast for uint256; 21 | | using SafeCast for int256; 22 | | using Price for Price.Props; 23 | | using Position for Position.Props; 24 | | using Order for Order.Props; 25 | | 26 | | // @dev UpdatePositionParams struct used in increasePosition and decreasePosition 27 | | // to avoid stack too deep errors 28 | | // 29 | | // @param contracts BaseOrderUtils.ExecuteOrderParamsContracts 30 | | // @param market the values of the trading market 31 | | // @param order the decrease position order 32 | | // @param orderKey the key of the order 33 | | // @param position the order's position 34 | | // @param positionKey the key of the order's position 35 | | struct UpdatePositionParams { 36 | | BaseOrderUtils.ExecuteOrderParamsContracts contracts; 37 | | Market.Props market; 38 | | Order.Props order; 39 | | bytes32 orderKey; 40 | | Position.Props position; 41 | | bytes32 positionKey; 42 | | Order.SecondaryOrderType secondaryOrderType; 43 | | } 44 | | 45 | | // @param dataStore DataStore 46 | | // @param eventEmitter EventEmitter 47 | | // @param oracle Oracle 48 | | // @param referralStorage IReferralStorage 49 | | struct UpdatePositionParamsContracts { 50 | | DataStore dataStore; 51 | | EventEmitter eventEmitter; 52 | | Oracle oracle; 53 | | SwapHandler swapHandler; 54 | | IReferralStorage referralStorage; 55 | | } 56 | | 57 | | struct WillPositionCollateralBeSufficientValues { 58 | | uint256 positionSizeInUsd; 59 | | uint256 positionCollateralAmount; 60 | | int256 realizedPnlUsd; 61 | | int256 openInterestDelta; 62 | | } 63 | | 64 | | struct DecreasePositionCollateralValuesOutput { 65 | | address outputToken; 66 | | uint256 outputAmount; 67 | | address secondaryOutputToken; 68 | | uint256 secondaryOutputAmount; 69 | | } 70 | | 71 | | // @dev ProcessCollateralValues struct used to contain the values in processCollateral 72 | | // @param executionPrice the order execution price 73 | | // @param remainingCollateralAmount the remaining collateral amount of the position 74 | | // @param positionPnlUsd the pnl of the position in USD 75 | | // @param sizeDeltaInTokens the change in position size in tokens 76 | | // @param priceImpactAmount the price impact in tokens 77 | | // @param priceImpactDiffUsd the price impact difference in USD 78 | | // @param pendingCollateralDeduction the pending collateral deduction 79 | | // @param output DecreasePositionCollateralValuesOutput 80 | | struct DecreasePositionCollateralValues { 81 | | uint256 executionPrice; 82 | | uint256 remainingCollateralAmount; 83 | | int256 basePnlUsd; 84 | | int256 uncappedBasePnlUsd; 85 | | uint256 sizeDeltaInTokens; 86 | | int256 priceImpactUsd; 87 | | uint256 priceImpactDiffUsd; 88 | | DecreasePositionCollateralValuesOutput output; 89 | | } 90 | | 91 | | // @dev DecreasePositionCache struct used in decreasePosition to 92 | | // avoid stack too deep errors 93 | | // @param prices the prices of the tokens in the market 94 | | // @param pnlToken the token that the pnl for the user is in, for long positions 95 | | // this is the market.longToken, for short positions this is the market.shortToken 96 | | // @param pnlTokenPrice the price of the pnlToken 97 | | // @param initialCollateralAmount the initial collateral amount 98 | | // @param nextPositionSizeInUsd the new position size in USD 99 | | // @param nextPositionBorrowingFactor the new position borrowing factor 100 | | struct DecreasePositionCache { 101 | | MarketUtils.MarketPrices prices; 102 | | int256 estimatedPositionPnlUsd; 103 | | int256 estimatedRealizedPnlUsd; 104 | | int256 estimatedRemainingPnlUsd; 105 | | address pnlToken; 106 | | Price.Props pnlTokenPrice; 107 | | Price.Props collateralTokenPrice; 108 | | uint256 initialCollateralAmount; 109 | | uint256 nextPositionSizeInUsd; 110 | | uint256 nextPositionBorrowingFactor; 111 | | } 112 | | 113 | | 114 | | struct GetPositionPnlUsdCache { 115 | | int256 positionValue; 116 | | int256 totalPositionPnl; 117 | | int256 uncappedTotalPositionPnl; 118 | | address pnlToken; 119 | | uint256 poolTokenAmount; 120 | | uint256 poolTokenPrice; 121 | | uint256 poolTokenUsd; 122 | | int256 poolPnl; 123 | | int256 cappedPoolPnl; 124 | | uint256 sizeDeltaInTokens; 125 | | int256 positionPnlUsd; 126 | | int256 uncappedPositionPnlUsd; 127 | | } 128 | | 129 | | struct IsPositionLiquidatableInfo { 130 | | int256 remainingCollateralUsd; 131 | | int256 minCollateralUsd; 132 | | int256 minCollateralUsdForLeverage; 133 | | } 134 | | 135 | | // @dev IsPositionLiquidatableCache struct used in isPositionLiquidatable 136 | | // to avoid stack too deep errors 137 | | // @param positionPnlUsd the position's pnl in USD 138 | | // @param minCollateralFactor the min collateral factor 139 | | // @param collateralTokenPrice the collateral token price 140 | | // @param collateralUsd the position's collateral in USD 141 | | // @param usdDeltaForPriceImpact the usdDelta value for the price impact calculation 142 | | // @param priceImpactUsd the price impact of closing the position in USD 143 | | struct IsPositionLiquidatableCache { 144 | | int256 positionPnlUsd; 145 | | uint256 minCollateralFactor; 146 | | Price.Props collateralTokenPrice; 147 | | uint256 collateralUsd; 148 | | int256 usdDeltaForPriceImpact; 149 | | int256 priceImpactUsd; 150 | | bool hasPositiveImpact; 151 | | } 152 | | 153 | | struct GetExecutionPriceForDecreaseCache { 154 | | int256 priceImpactUsd; 155 | | uint256 priceImpactDiffUsd; 156 | | uint256 executionPrice; 157 | | } 158 | | 159 | | // @dev get the position pnl in USD 160 | | // 161 | | // for long positions, pnl is calculated as: 162 | | // (position.sizeInTokens * indexTokenPrice) - position.sizeInUsd 163 | | // if position.sizeInTokens is larger for long positions, the position will have 164 | | // larger profits and smaller losses for the same changes in token price 165 | | // 166 | | // for short positions, pnl is calculated as: 167 | | // position.sizeInUsd - (position.sizeInTokens * indexTokenPrice) 168 | | // if position.sizeInTokens is smaller for long positions, the position will have 169 | | // larger profits and smaller losses for the same changes in token price 170 | | // 171 | | // @param position the position values 172 | | // @param sizeDeltaUsd the change in position size 173 | | // @param indexTokenPrice the price of the index token 174 | | // 175 | | // @return (positionPnlUsd, uncappedPositionPnlUsd, sizeDeltaInTokens) 176 | * | function getPositionPnlUsd( 177 | | DataStore dataStore, 178 | | Market.Props memory market, 179 | | MarketUtils.MarketPrices memory prices, 180 | | Position.Props memory position, 181 | | uint256 sizeDeltaUsd 182 | * | ) internal view returns (int256, int256, uint256) { 183 | * | GetPositionPnlUsdCache memory cache; 184 | | 185 | * | uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false); 186 | | 187 | | // position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens 188 | * | cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256(); 189 | * | cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue; 190 | * | cache.uncappedTotalPositionPnl = cache.totalPositionPnl; 191 | | 192 | * | if (cache.totalPositionPnl > 0) { 193 | * | cache.pnlToken = position.isLong() ? market.longToken : market.shortToken; 194 | * | cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken); 195 | * | cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min; 196 | * | cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice; 197 | * | cache.poolPnl = MarketUtils.getPnl( 198 | * | dataStore, 199 | * | market, 200 | * | prices.indexTokenPrice, 201 | * | position.isLong(), 202 | * | true 203 | | ); 204 | | 205 | * | cache.cappedPoolPnl = MarketUtils.getCappedPnl( 206 | * | dataStore, 207 | * | market.marketToken, 208 | * | position.isLong(), 209 | * | cache.poolPnl, 210 | * | cache.poolTokenUsd, 211 | | Keys.MAX_PNL_FACTOR_FOR_TRADERS 212 | | ); 213 | | 214 | * | if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) { 215 | | cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256()); 216 | | } 217 | | } 218 | | 219 | * | if (position.sizeInUsd() == sizeDeltaUsd) { 220 | * | cache.sizeDeltaInTokens = position.sizeInTokens(); 221 | | } else { 222 | * | if (position.isLong()) { 223 | * | cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd()); 224 | | } else { 225 | | cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd(); 226 | | } 227 | | } 228 | | 229 | * | cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens()); 230 | * | cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens()); 231 | | 232 | * | return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens); 233 | | } 234 | | 235 | | // @dev validate that a position is not empty 236 | | // @param position the position values 237 | * | function validateNonEmptyPosition(Position.Props memory position) internal pure { 238 | * | if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) { 239 | * | revert Errors.EmptyPosition(); 240 | | } 241 | | } 242 | | 243 | | // @dev check if a position is valid 244 | | // @param dataStore DataStore 245 | | // @param referralStorage IReferralStorage 246 | | // @param position the position values 247 | | // @param market the market values 248 | | // @param prices the prices of the tokens in the market 249 | | // @param shouldValidateMinCollateralUsd whether min collateral usd needs to be validated 250 | | // validation is skipped for decrease position to prevent reverts in case the order size 251 | | // is just slightly smaller than the position size 252 | | // in decrease position, the remaining collateral is estimated at the start, and the order 253 | | // size is updated to match the position size if the remaining collateral will be less than 254 | | // the min collateral usd 255 | | // since this is an estimate, there may be edge cases where there is a small remaining position size 256 | | // and small amount of collateral remaining 257 | | // validation is skipped for this case as it is preferred for the order to be executed 258 | | // since the small amount of collateral remaining only impacts the potential payment of liquidation 259 | | // keepers 260 | * | function validatePosition( 261 | | DataStore dataStore, 262 | | IReferralStorage referralStorage, 263 | | Position.Props memory position, 264 | | Market.Props memory market, 265 | | MarketUtils.MarketPrices memory prices, 266 | | bool shouldValidateMinPositionSize, 267 | | bool shouldValidateMinCollateralUsd 268 | * | ) internal view { 269 | * | if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) { 270 | * | revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens()); 271 | | } 272 | | 273 | * | MarketUtils.validateEnabledMarket(dataStore, market.marketToken); 274 | * | MarketUtils.validateMarketCollateralToken(market, position.collateralToken()); 275 | | 276 | * | if (shouldValidateMinPositionSize) { 277 | * | uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD); 278 | * | if (position.sizeInUsd() < minPositionSizeUsd) { 279 | * | revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd); 280 | | } 281 | | } 282 | | 283 | * | (bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable( 284 | * | dataStore, 285 | * | referralStorage, 286 | * | position, 287 | * | market, 288 | * | prices, 289 | * | shouldValidateMinCollateralUsd 290 | | ); 291 | | 292 | * | if (isLiquidatable) { 293 | * | revert Errors.LiquidatablePosition( 294 | * | reason, 295 | * | info.remainingCollateralUsd, 296 | * | info.minCollateralUsd, 297 | * | info.minCollateralUsdForLeverage 298 | | ); 299 | | } 300 | | } 301 | | 302 | | // @dev check if a position is liquidatable 303 | | // @param dataStore DataStore 304 | | // @param referralStorage IReferralStorage 305 | | // @param position the position values 306 | | // @param market the market values 307 | | // @param prices the prices of the tokens in the market 308 | * | function isPositionLiquidatable( 309 | | DataStore dataStore, 310 | | IReferralStorage referralStorage, 311 | | Position.Props memory position, 312 | | Market.Props memory market, 313 | | MarketUtils.MarketPrices memory prices, 314 | | bool shouldValidateMinCollateralUsd 315 | * | ) internal view returns (bool, string memory, IsPositionLiquidatableInfo memory) { 316 | * | IsPositionLiquidatableCache memory cache; 317 | * | IsPositionLiquidatableInfo memory info; 318 | | 319 | * | (cache.positionPnlUsd, /* int256 uncappedBasePnlUsd */, /* uint256 sizeDeltaInTokens */) = getPositionPnlUsd( 320 | * | dataStore, 321 | * | market, 322 | * | prices, 323 | * | position, 324 | * | position.sizeInUsd() 325 | | ); 326 | | 327 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice( 328 | * | position.collateralToken(), 329 | * | market, 330 | * | prices 331 | | ); 332 | | 333 | * | cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min; 334 | | 335 | | // calculate the usdDeltaForPriceImpact for fully closing the position 336 | * | cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256(); 337 | | 338 | * | cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd( 339 | * | PositionPricingUtils.GetPriceImpactUsdParams( 340 | * | dataStore, 341 | * | market, 342 | * | cache.usdDeltaForPriceImpact, 343 | * | position.isLong() 344 | | ) 345 | | ); 346 | | 347 | * | cache.hasPositiveImpact = cache.priceImpactUsd > 0; 348 | | 349 | | // even if there is a large positive price impact, positions that would be liquidated 350 | | // if the positive price impact is reduced should not be allowed to be created 351 | | // as they would be easily liquidated if the price impact changes 352 | | // cap the priceImpactUsd to zero to prevent these positions from being created 353 | * | if (cache.priceImpactUsd >= 0) { 354 | * | cache.priceImpactUsd = 0; 355 | | } else { 356 | | uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations( 357 | | dataStore, 358 | | market.marketToken 359 | | ); 360 | | 361 | | // if there is a large build up of open interest and a sudden large price movement 362 | | // it may result in a large imbalance between longs and shorts 363 | | // this could result in very large price impact temporarily 364 | | // cap the max negative price impact to prevent cascading liquidations 365 | | int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256(); 366 | | if (cache.priceImpactUsd < maxNegativePriceImpactUsd) { 367 | | cache.priceImpactUsd = maxNegativePriceImpactUsd; 368 | | } 369 | | } 370 | | 371 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams( 372 | * | dataStore, // dataStore 373 | * | referralStorage, // referralStorage 374 | * | position, // position 375 | * | cache.collateralTokenPrice, //collateralTokenPrice 376 | * | cache.hasPositiveImpact, // forPositiveImpact 377 | * | market.longToken, // longToken 378 | * | market.shortToken, // shortToken 379 | * | position.sizeInUsd(), // sizeDeltaUsd 380 | * | address(0) // uiFeeReceiver 381 | | ); 382 | | 383 | * | PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams); 384 | | 385 | | // the totalCostAmount is in tokens, use collateralTokenPrice.min to calculate the cost in USD 386 | | // since in PositionPricingUtils.getPositionFees the totalCostAmount in tokens was calculated 387 | | // using collateralTokenPrice.min 388 | * | uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min; 389 | | 390 | | // the position's pnl is counted as collateral for the liquidation check 391 | | // as a position in profit should not be liquidated if the pnl is sufficient 392 | | // to cover the position's fees 393 | * | info.remainingCollateralUsd = 394 | * | cache.collateralUsd.toInt256() 395 | * | + cache.positionPnlUsd 396 | * | + cache.priceImpactUsd 397 | * | - collateralCostUsd.toInt256(); 398 | | 399 | * | cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken); 400 | | 401 | | // validate if (remaining collateral) / position.size is less than the min collateral factor (max leverage exceeded) 402 | | // this validation includes the position fee to be paid when closing the position 403 | | // i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position 404 | * | info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256(); 405 | | 406 | * | if (shouldValidateMinCollateralUsd) { 407 | * | info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256(); 408 | * | if (info.remainingCollateralUsd < info.minCollateralUsd) { 409 | * | return (true, "min collateral", info); 410 | | } 411 | | } 412 | | 413 | * | if (info.remainingCollateralUsd <= 0) { 414 | | return (true, "< 0", info); 415 | | } 416 | | 417 | * | if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) { 418 | * | return (true, "min collateral for leverage", info); 419 | | } 420 | | 421 | * | return (false, "", info); 422 | | } 423 | | 424 | | // fees and price impact are not included for the willPositionCollateralBeSufficient validation 425 | | // this is because this validation is meant to guard against a specific scenario of price impact 426 | | // gaming 427 | | // 428 | | // price impact could be gamed by opening high leverage positions, if the price impact 429 | | // that should be charged is higher than the amount of collateral in the position 430 | | // then a user could pay less price impact than what is required, and there is a risk that 431 | | // price manipulation could be profitable if the price impact cost is less than it should be 432 | | // 433 | | // this check should be sufficient even without factoring in fees as fees should have a minimal impact 434 | | // it may be possible that funding or borrowing fees are accumulated and need to be deducted which could 435 | | // lead to a user paying less price impact than they should, however gaming of this form should be difficult 436 | | // since the funding and borrowing fees would still add up for the user's cost 437 | | // 438 | | // another possibility would be if a user opens a large amount of both long and short positions, and 439 | | // funding fees are paid from one side to the other, but since most of the open interest is owned by the 440 | | // user the user earns most of the paid cost, in this scenario the borrowing fees should still be significant 441 | | // since some time would be required for the funding fees to accumulate 442 | | // 443 | | // fees and price impact are validated in the validatePosition check 444 | * | function willPositionCollateralBeSufficient( 445 | | DataStore dataStore, 446 | | Market.Props memory market, 447 | | MarketUtils.MarketPrices memory prices, 448 | | address collateralToken, 449 | | bool isLong, 450 | | WillPositionCollateralBeSufficientValues memory values 451 | * | ) internal view returns (bool, int256) { 452 | * | Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice( 453 | * | collateralToken, 454 | * | market, 455 | * | prices 456 | | ); 457 | | 458 | * | int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256(); 459 | | 460 | | // deduct realized pnl if it is negative since this would be paid from 461 | | // the position's collateral 462 | * | if (values.realizedPnlUsd < 0) { 463 | * | remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd; 464 | | } 465 | | 466 | * | if (remainingCollateralUsd < 0) { 467 | * | return (false, remainingCollateralUsd); 468 | | } 469 | | 470 | | // the min collateral factor will increase as the open interest for a market increases 471 | | // this may lead to previously created limit increase orders not being executable 472 | | // 473 | | // the position's pnl is not factored into the remainingCollateralUsd value, since 474 | | // factoring in a positive pnl may allow the user to manipulate price and bypass this check 475 | | // it may be useful to factor in a negative pnl for this check, this can be added if required 476 | * | uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest( 477 | * | dataStore, 478 | * | market, 479 | * | values.openInterestDelta, 480 | * | isLong 481 | | ); 482 | | 483 | * | uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken); 484 | | // use the minCollateralFactor for the market if it is larger 485 | * | if (minCollateralFactorForMarket > minCollateralFactor) { 486 | * | minCollateralFactor = minCollateralFactorForMarket; 487 | | } 488 | | 489 | * | int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256(); 490 | * | bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage; 491 | | 492 | * | return (willBeSufficient, remainingCollateralUsd); 493 | | } 494 | | 495 | * | function updateFundingAndBorrowingState( 496 | | DataStore dataStore, 497 | | EventEmitter eventEmitter, 498 | | Market.Props memory market, 499 | | MarketUtils.MarketPrices memory prices 500 | | ) internal { 501 | | // update the funding amount per size for the market 502 | * | MarketUtils.updateFundingState( 503 | * | dataStore, 504 | * | eventEmitter, 505 | * | market, 506 | * | prices 507 | | ); 508 | | 509 | | // update the cumulative borrowing factor for longs 510 | * | MarketUtils.updateCumulativeBorrowingFactor( 511 | * | dataStore, 512 | * | eventEmitter, 513 | * | market, 514 | * | prices, 515 | * | true // isLong 516 | | ); 517 | | 518 | | // update the cumulative borrowing factor for shorts 519 | * | MarketUtils.updateCumulativeBorrowingFactor( 520 | * | dataStore, 521 | * | eventEmitter, 522 | * | market, 523 | * | prices, 524 | * | false // isLong 525 | | ); 526 | | } 527 | | 528 | * | function updateTotalBorrowing( 529 | | PositionUtils.UpdatePositionParams memory params, 530 | | uint256 nextPositionSizeInUsd, 531 | | uint256 nextPositionBorrowingFactor 532 | | ) internal { 533 | * | MarketUtils.updateTotalBorrowing( 534 | * | params.contracts.dataStore, // dataStore 535 | * | params.market.marketToken, // market 536 | * | params.position.isLong(), // isLong 537 | * | params.position.sizeInUsd(), // prevPositionSizeInUsd 538 | * | params.position.borrowingFactor(), // prevPositionBorrowingFactor 539 | * | nextPositionSizeInUsd, // nextPositionSizeInUsd 540 | * | nextPositionBorrowingFactor // nextPositionBorrowingFactor 541 | | ); 542 | | } 543 | | 544 | | // the order.receiver is meant to allow the output of an order to be 545 | | // received by an address that is different from the position.account 546 | | // address 547 | | // for funding fees, the funds are still credited to the owner 548 | | // of the position indicated by order.account 549 | * | function incrementClaimableFundingAmount( 550 | | PositionUtils.UpdatePositionParams memory params, 551 | | PositionPricingUtils.PositionFees memory fees 552 | | ) internal { 553 | | // if the position has negative funding fees, distribute it to allow it to be claimable 554 | * | if (fees.funding.claimableLongTokenAmount > 0) { 555 | * | MarketUtils.incrementClaimableFundingAmount( 556 | * | params.contracts.dataStore, 557 | * | params.contracts.eventEmitter, 558 | * | params.market.marketToken, 559 | * | params.market.longToken, 560 | * | params.order.account(), 561 | * | fees.funding.claimableLongTokenAmount 562 | | ); 563 | | } 564 | | 565 | * | if (fees.funding.claimableShortTokenAmount > 0) { 566 | * | MarketUtils.incrementClaimableFundingAmount( 567 | * | params.contracts.dataStore, 568 | * | params.contracts.eventEmitter, 569 | * | params.market.marketToken, 570 | * | params.market.shortToken, 571 | * | params.order.account(), 572 | * | fees.funding.claimableShortTokenAmount 573 | | ); 574 | | } 575 | | } 576 | | 577 | * | function updateOpenInterest( 578 | | PositionUtils.UpdatePositionParams memory params, 579 | | int256 sizeDeltaUsd, 580 | | int256 sizeDeltaInTokens 581 | | ) internal { 582 | * | if (sizeDeltaUsd != 0) { 583 | * | MarketUtils.applyDeltaToOpenInterest( 584 | * | params.contracts.dataStore, 585 | * | params.contracts.eventEmitter, 586 | * | params.market, 587 | * | params.position.collateralToken(), 588 | * | params.position.isLong(), 589 | * | sizeDeltaUsd 590 | | ); 591 | | 592 | * | MarketUtils.applyDeltaToOpenInterestInTokens( 593 | * | params.contracts.dataStore, 594 | * | params.contracts.eventEmitter, 595 | * | params.position.market(), 596 | * | params.position.collateralToken(), 597 | * | params.position.isLong(), 598 | * | sizeDeltaInTokens 599 | | ); 600 | | } 601 | | } 602 | | 603 | * | function handleReferral( 604 | | PositionUtils.UpdatePositionParams memory params, 605 | | PositionPricingUtils.PositionFees memory fees 606 | | ) internal { 607 | * | ReferralUtils.incrementAffiliateReward( 608 | * | params.contracts.dataStore, 609 | * | params.contracts.eventEmitter, 610 | * | params.position.market(), 611 | * | params.position.collateralToken(), 612 | * | fees.referral.affiliate, 613 | * | fees.referral.affiliateRewardAmount 614 | | ); 615 | | } 616 | | 617 | | // returns priceImpactUsd, priceImpactAmount, sizeDeltaInTokens, executionPrice 618 | * | function getExecutionPriceForIncrease( 619 | | UpdatePositionParams memory params, 620 | | Price.Props memory indexTokenPrice 621 | * | ) internal view returns (int256, int256, uint256, uint256) { 622 | | // note that the executionPrice is not validated against the order.acceptablePrice value 623 | | // if the sizeDeltaUsd is zero 624 | | // for limit orders the order.triggerPrice should still have been validated 625 | * | if (params.order.sizeDeltaUsd() == 0) { 626 | | // increase order: 627 | | // - long: use the larger price 628 | | // - short: use the smaller price 629 | * | return (0, 0, 0, indexTokenPrice.pickPrice(params.position.isLong())); 630 | | } 631 | | 632 | * | int256 priceImpactUsd = PositionPricingUtils.getPriceImpactUsd( 633 | * | PositionPricingUtils.GetPriceImpactUsdParams( 634 | * | params.contracts.dataStore, 635 | * | params.market, 636 | * | params.order.sizeDeltaUsd().toInt256(), 637 | * | params.order.isLong() 638 | | ) 639 | | ); 640 | | 641 | | // cap priceImpactUsd based on the amount available in the position impact pool 642 | * | priceImpactUsd = MarketUtils.getCappedPositionImpactUsd( 643 | * | params.contracts.dataStore, 644 | * | params.market.marketToken, 645 | * | indexTokenPrice, 646 | * | priceImpactUsd, 647 | * | params.order.sizeDeltaUsd() 648 | | ); 649 | | 650 | | // for long positions 651 | | // 652 | | // if price impact is positive, the sizeDeltaInTokens would be increased by the priceImpactAmount 653 | | // the priceImpactAmount should be minimized 654 | | // 655 | | // if price impact is negative, the sizeDeltaInTokens would be decreased by the priceImpactAmount 656 | | // the priceImpactAmount should be maximized 657 | | 658 | | // for short positions 659 | | // 660 | | // if price impact is positive, the sizeDeltaInTokens would be decreased by the priceImpactAmount 661 | | // the priceImpactAmount should be minimized 662 | | // 663 | | // if price impact is negative, the sizeDeltaInTokens would be increased by the priceImpactAmount 664 | | // the priceImpactAmount should be maximized 665 | | 666 | * | int256 priceImpactAmount; 667 | | 668 | * | if (priceImpactUsd > 0) { 669 | | // use indexTokenPrice.max and round down to minimize the priceImpactAmount 670 | | priceImpactAmount = priceImpactUsd / indexTokenPrice.max.toInt256(); 671 | | } else { 672 | | // use indexTokenPrice.min and round up to maximize the priceImpactAmount 673 | * | priceImpactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, indexTokenPrice.min); 674 | | } 675 | | 676 | * | uint256 baseSizeDeltaInTokens; 677 | | 678 | * | if (params.position.isLong()) { 679 | | // round the number of tokens for long positions down 680 | * | baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / indexTokenPrice.max; 681 | | } else { 682 | | // round the number of tokens for short positions up 683 | * | baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), indexTokenPrice.min); 684 | | } 685 | | 686 | * | int256 sizeDeltaInTokens; 687 | * | if (params.position.isLong()) { 688 | * | sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() + priceImpactAmount; 689 | | } else { 690 | * | sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() - priceImpactAmount; 691 | | } 692 | | 693 | * | if (sizeDeltaInTokens < 0) { 694 | | revert Errors.PriceImpactLargerThanOrderSize(priceImpactUsd, params.order.sizeDeltaUsd()); 695 | | } 696 | | 697 | | // using increase of long positions as an example 698 | | // if price is $2000, sizeDeltaUsd is $5000, priceImpactUsd is -$1000 699 | | // priceImpactAmount = -1000 / 2000 = -0.5 700 | | // baseSizeDeltaInTokens = 5000 / 2000 = 2.5 701 | | // sizeDeltaInTokens = 2.5 - 0.5 = 2 702 | | // executionPrice = 5000 / 2 = $2500 703 | * | uint256 executionPrice = BaseOrderUtils.getExecutionPriceForIncrease( 704 | * | params.order.sizeDeltaUsd(), 705 | * | sizeDeltaInTokens.toUint256(), 706 | * | params.order.acceptablePrice(), 707 | * | params.position.isLong() 708 | | ); 709 | | 710 | * | return (priceImpactUsd, priceImpactAmount, sizeDeltaInTokens.toUint256(), executionPrice); 711 | | } 712 | | 713 | | // returns priceImpactUsd, priceImpactDiffUsd, executionPrice 714 | * | function getExecutionPriceForDecrease( 715 | | UpdatePositionParams memory params, 716 | | Price.Props memory indexTokenPrice 717 | * | ) internal view returns (int256, uint256, uint256) { 718 | * | uint256 sizeDeltaUsd = params.order.sizeDeltaUsd(); 719 | | 720 | | // note that the executionPrice is not validated against the order.acceptablePrice value 721 | | // if the sizeDeltaUsd is zero 722 | | // for limit orders the order.triggerPrice should still have been validated 723 | * | if (sizeDeltaUsd == 0) { 724 | | // decrease order: 725 | | // - long: use the smaller price 726 | | // - short: use the larger price 727 | * | return (0, 0, indexTokenPrice.pickPrice(!params.position.isLong())); 728 | | } 729 | | 730 | * | GetExecutionPriceForDecreaseCache memory cache; 731 | | 732 | * | cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd( 733 | * | PositionPricingUtils.GetPriceImpactUsdParams( 734 | * | params.contracts.dataStore, 735 | * | params.market, 736 | * | -sizeDeltaUsd.toInt256(), 737 | * | params.order.isLong() 738 | | ) 739 | | ); 740 | | 741 | | // cap priceImpactUsd based on the amount available in the position impact pool 742 | * | cache.priceImpactUsd = MarketUtils.getCappedPositionImpactUsd( 743 | * | params.contracts.dataStore, 744 | * | params.market.marketToken, 745 | * | indexTokenPrice, 746 | * | cache.priceImpactUsd, 747 | * | sizeDeltaUsd 748 | | ); 749 | | 750 | * | if (cache.priceImpactUsd < 0) { 751 | | uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactor( 752 | | params.contracts.dataStore, 753 | | params.market.marketToken, 754 | | false 755 | | ); 756 | | 757 | | // convert the max price impact to the min negative value 758 | | // e.g. if sizeDeltaUsd is 10,000 and maxPriceImpactFactor is 2% 759 | | // then minPriceImpactUsd = -200 760 | | int256 minPriceImpactUsd = -Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256(); 761 | | 762 | | // cap priceImpactUsd to the min negative value and store the difference in priceImpactDiffUsd 763 | | // e.g. if priceImpactUsd is -500 and minPriceImpactUsd is -200 764 | | // then set priceImpactDiffUsd to -200 - -500 = 300 765 | | // set priceImpactUsd to -200 766 | | if (cache.priceImpactUsd < minPriceImpactUsd) { 767 | | cache.priceImpactDiffUsd = (minPriceImpactUsd - cache.priceImpactUsd).toUint256(); 768 | | cache.priceImpactUsd = minPriceImpactUsd; 769 | | } 770 | | } 771 | | 772 | | // the executionPrice is calculated after the price impact is capped 773 | | // so the output amount directly received by the user may not match 774 | | // the executionPrice, the difference would be stored as a 775 | | // claimable amount 776 | * | cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease( 777 | * | indexTokenPrice, 778 | * | params.position.sizeInUsd(), 779 | * | params.position.sizeInTokens(), 780 | * | sizeDeltaUsd, 781 | * | cache.priceImpactUsd, 782 | * | params.order.acceptablePrice(), 783 | * | params.position.isLong() 784 | | ); 785 | | 786 | * | return (cache.priceImpactUsd, cache.priceImpactDiffUsd, cache.executionPrice); 787 | | } 788 | | 789 | | } 790 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/price/Price.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title Price 6 | | // @dev Struct for prices 7 | * | library Price { 8 | | // @param min the min price 9 | | // @param max the max price 10 | | struct Props { 11 | | uint256 min; 12 | | uint256 max; 13 | | } 14 | | 15 | | // @dev check if a price is empty 16 | | // @param props Props 17 | | // @return whether a price is empty 18 | * | function isEmpty(Props memory props) internal pure returns (bool) { 19 | * | return props.min == 0 || props.max == 0; 20 | | } 21 | | 22 | | // @dev get the average of the min and max values 23 | | // @param props Props 24 | | // @return the average of the min and max values 25 | * | function midPrice(Props memory props) internal pure returns (uint256) { 26 | * | return (props.max + props.min) / 2; 27 | | } 28 | | 29 | | // @dev pick either the min or max value 30 | | // @param props Props 31 | | // @param maximize whether to pick the min or max value 32 | | // @return either the min or max value 33 | * | function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) { 34 | * | return maximize ? props.max : props.min; 35 | | } 36 | | 37 | | // @dev pick the min or max price depending on whether it is for a long or short position 38 | | // and whether the pending pnl should be maximized or not 39 | | // @param props Props 40 | | // @param isLong whether it is for a long or short position 41 | | // @param maximize whether the pnl should be maximized or not 42 | | // @return the min or max price 43 | * | function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) { 44 | | // for long positions, pick the larger price to maximize pnl 45 | | // for short positions, pick the smaller price to maximize pnl 46 | * | if (isLong) { 47 | * | return maximize ? props.max : props.min; 48 | | } 49 | | 50 | * | return maximize ? props.min : props.max; 51 | | } 52 | | } 53 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/ISwapPricingUtils.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | interface ISwapPricingUtils { 6 | | enum SwapPricingType { 7 | | TwoStep, 8 | | Shift, 9 | | Atomic 10 | | } 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/PositionPricingUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../market/MarketUtils.sol"; 8 | | 9 | | import "../utils/Precision.sol"; 10 | | import "../utils/Calc.sol"; 11 | | 12 | | import "./PricingUtils.sol"; 13 | | 14 | | import "../referral/IReferralStorage.sol"; 15 | | import "../referral/ReferralUtils.sol"; 16 | | 17 | | // @title PositionPricingUtils 18 | | // @dev Library for position pricing functions 19 | * | library PositionPricingUtils { 20 | | using SignedMath for int256; 21 | | using SafeCast for uint256; 22 | | using SafeCast for int256; 23 | | using Position for Position.Props; 24 | | using Price for Price.Props; 25 | | 26 | | using EventUtils for EventUtils.AddressItems; 27 | | using EventUtils for EventUtils.UintItems; 28 | | using EventUtils for EventUtils.IntItems; 29 | | using EventUtils for EventUtils.BoolItems; 30 | | using EventUtils for EventUtils.Bytes32Items; 31 | | using EventUtils for EventUtils.BytesItems; 32 | | using EventUtils for EventUtils.StringItems; 33 | | 34 | | struct GetPositionFeesParams { 35 | | DataStore dataStore; 36 | | IReferralStorage referralStorage; 37 | | Position.Props position; 38 | | Price.Props collateralTokenPrice; 39 | | bool forPositiveImpact; 40 | | address longToken; 41 | | address shortToken; 42 | | uint256 sizeDeltaUsd; 43 | | address uiFeeReceiver; 44 | | } 45 | | 46 | | // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to avoid stack 47 | | // too deep errors 48 | | // @param dataStore DataStore 49 | | // @param market the market to check 50 | | // @param usdDelta the change in position size in USD 51 | | // @param isLong whether the position is long or short 52 | | struct GetPriceImpactUsdParams { 53 | | DataStore dataStore; 54 | | Market.Props market; 55 | | int256 usdDelta; 56 | | bool isLong; 57 | | } 58 | | 59 | | // @dev OpenInterestParams struct to contain open interest values 60 | | // @param longOpenInterest the amount of long open interest 61 | | // @param shortOpenInterest the amount of short open interest 62 | | // @param nextLongOpenInterest the updated amount of long open interest 63 | | // @param nextShortOpenInterest the updated amount of short open interest 64 | | struct OpenInterestParams { 65 | | uint256 longOpenInterest; 66 | | uint256 shortOpenInterest; 67 | | uint256 nextLongOpenInterest; 68 | | uint256 nextShortOpenInterest; 69 | | } 70 | | 71 | | // @dev PositionFees struct to contain fee values 72 | | // @param feeReceiverAmount the amount for the fee receiver 73 | | // @param feeAmountForPool the amount of fees for the pool 74 | | // @param positionFeeAmountForPool the position fee amount for the pool 75 | | // @param positionFeeAmount the fee amount for increasing / decreasing the position 76 | | // @param borrowingFeeAmount the borrowing fee amount 77 | | // @param totalCostAmount the total cost amount in tokens 78 | | struct PositionFees { 79 | | PositionReferralFees referral; 80 | | PositionFundingFees funding; 81 | | PositionBorrowingFees borrowing; 82 | | PositionUiFees ui; 83 | | Price.Props collateralTokenPrice; 84 | | uint256 positionFeeFactor; 85 | | uint256 protocolFeeAmount; 86 | | uint256 positionFeeReceiverFactor; 87 | | uint256 feeReceiverAmount; 88 | | uint256 feeAmountForPool; 89 | | uint256 positionFeeAmountForPool; 90 | | uint256 positionFeeAmount; 91 | | uint256 totalCostAmountExcludingFunding; 92 | | uint256 totalCostAmount; 93 | | } 94 | | 95 | | // @param affiliate the referral affiliate of the trader 96 | | // @param traderDiscountAmount the discount amount for the trader 97 | | // @param affiliateRewardAmount the affiliate reward amount 98 | | struct PositionReferralFees { 99 | | bytes32 referralCode; 100 | | address affiliate; 101 | | address trader; 102 | | uint256 totalRebateFactor; 103 | | uint256 traderDiscountFactor; 104 | | uint256 totalRebateAmount; 105 | | uint256 traderDiscountAmount; 106 | | uint256 affiliateRewardAmount; 107 | | } 108 | | 109 | | struct PositionBorrowingFees { 110 | | uint256 borrowingFeeUsd; 111 | | uint256 borrowingFeeAmount; 112 | | uint256 borrowingFeeReceiverFactor; 113 | | uint256 borrowingFeeAmountForFeeReceiver; 114 | | } 115 | | 116 | | // @param fundingFeeAmount the position's funding fee amount 117 | | // @param claimableLongTokenAmount the negative funding fee in long token that is claimable 118 | | // @param claimableShortTokenAmount the negative funding fee in short token that is claimable 119 | | // @param latestLongTokenFundingAmountPerSize the latest long token funding 120 | | // amount per size for the market 121 | | // @param latestShortTokenFundingAmountPerSize the latest short token funding 122 | | // amount per size for the market 123 | | struct PositionFundingFees { 124 | | uint256 fundingFeeAmount; 125 | | uint256 claimableLongTokenAmount; 126 | | uint256 claimableShortTokenAmount; 127 | | uint256 latestFundingFeeAmountPerSize; 128 | | uint256 latestLongTokenClaimableFundingAmountPerSize; 129 | | uint256 latestShortTokenClaimableFundingAmountPerSize; 130 | | } 131 | | 132 | | struct PositionUiFees { 133 | | address uiFeeReceiver; 134 | | uint256 uiFeeReceiverFactor; 135 | | uint256 uiFeeAmount; 136 | | } 137 | | 138 | | // @dev get the price impact in USD for a position increase / decrease 139 | | // @param params GetPriceImpactUsdParams 140 | * | function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) { 141 | * | OpenInterestParams memory openInterestParams = getNextOpenInterest(params); 142 | | 143 | * | int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams); 144 | | 145 | | // the virtual price impact calculation is skipped if the price impact 146 | | // is positive since the action is helping to balance the pool 147 | | // 148 | | // in case two virtual pools are unbalanced in a different direction 149 | | // e.g. pool0 has more longs than shorts while pool1 has less longs 150 | | // than shorts 151 | | // not skipping the virtual price impact calculation would lead to 152 | | // a negative price impact for any trade on either pools and would 153 | | // disincentivise the balancing of pools 154 | * | if (priceImpactUsd >= 0) { return priceImpactUsd; } 155 | | 156 | * | (bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken); 157 | * | if (!hasVirtualInventory) { return priceImpactUsd; } 158 | | 159 | | OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory); 160 | | int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory); 161 | | 162 | | return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd; 163 | | } 164 | | 165 | | // @dev get the price impact in USD for a position increase / decrease 166 | | // @param dataStore DataStore 167 | | // @param market the trading market 168 | | // @param openInterestParams OpenInterestParams 169 | * | function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256) { 170 | * | uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest); 171 | * | uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest); 172 | | 173 | | // check whether an improvement in balance comes from causing the balance to switch sides 174 | | // for example, if there is $2000 of ETH and $1000 of USDC in the pool 175 | | // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not 176 | | // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case 177 | * | bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest; 178 | * | uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market)); 179 | | 180 | * | if (isSameSideRebalance) { 181 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd; 182 | * | uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, hasPositiveImpact); 183 | | 184 | * | return PricingUtils.getPriceImpactUsdForSameSideRebalance( 185 | * | initialDiffUsd, 186 | * | nextDiffUsd, 187 | * | impactFactor, 188 | * | impactExponentFactor 189 | | ); 190 | | } else { 191 | * | (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market); 192 | | 193 | * | return PricingUtils.getPriceImpactUsdForCrossoverRebalance( 194 | * | initialDiffUsd, 195 | * | nextDiffUsd, 196 | * | positiveImpactFactor, 197 | * | negativeImpactFactor, 198 | * | impactExponentFactor 199 | | ); 200 | | } 201 | | } 202 | | 203 | | // @dev get the next open interest values 204 | | // @param params GetPriceImpactUsdParams 205 | | // @return OpenInterestParams 206 | * | function getNextOpenInterest( 207 | | GetPriceImpactUsdParams memory params 208 | * | ) internal view returns (OpenInterestParams memory) { 209 | * | uint256 longOpenInterest = MarketUtils.getOpenInterest( 210 | * | params.dataStore, 211 | * | params.market, 212 | * | true 213 | | ); 214 | | 215 | * | uint256 shortOpenInterest = MarketUtils.getOpenInterest( 216 | * | params.dataStore, 217 | * | params.market, 218 | * | false 219 | | ); 220 | | 221 | * | return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest); 222 | | } 223 | | 224 | | function getNextOpenInterestForVirtualInventory( 225 | | GetPriceImpactUsdParams memory params, 226 | | int256 virtualInventory 227 | | ) internal pure returns (OpenInterestParams memory) { 228 | | uint256 longOpenInterest; 229 | | uint256 shortOpenInterest; 230 | | 231 | | // if virtualInventory is more than zero it means that 232 | | // tokens were virtually sold to the pool, so set shortOpenInterest 233 | | // to the virtualInventory value 234 | | // if virtualInventory is less than zero it means that 235 | | // tokens were virtually bought from the pool, so set longOpenInterest 236 | | // to the virtualInventory value 237 | | if (virtualInventory > 0) { 238 | | shortOpenInterest = virtualInventory.toUint256(); 239 | | } else { 240 | | longOpenInterest = (-virtualInventory).toUint256(); 241 | | } 242 | | 243 | | // the virtual long and short open interest is adjusted by the usdDelta 244 | | // to prevent an underflow in getNextOpenInterestParams 245 | | // price impact depends on the change in USD balance, so offsetting both 246 | | // values equally should not change the price impact calculation 247 | | if (params.usdDelta < 0) { 248 | | uint256 offset = (-params.usdDelta).toUint256(); 249 | | longOpenInterest += offset; 250 | | shortOpenInterest += offset; 251 | | } 252 | | 253 | | return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest); 254 | | } 255 | | 256 | * | function getNextOpenInterestParams( 257 | | GetPriceImpactUsdParams memory params, 258 | | uint256 longOpenInterest, 259 | | uint256 shortOpenInterest 260 | * | ) internal pure returns (OpenInterestParams memory) { 261 | * | uint256 nextLongOpenInterest = longOpenInterest; 262 | * | uint256 nextShortOpenInterest = shortOpenInterest; 263 | | 264 | * | if (params.isLong) { 265 | * | if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) { 266 | | revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest); 267 | | } 268 | | 269 | * | nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta); 270 | | } else { 271 | * | if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) { 272 | | revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest); 273 | | } 274 | | 275 | * | nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta); 276 | | } 277 | | 278 | * | OpenInterestParams memory openInterestParams = OpenInterestParams( 279 | * | longOpenInterest, 280 | * | shortOpenInterest, 281 | * | nextLongOpenInterest, 282 | * | nextShortOpenInterest 283 | | ); 284 | | 285 | * | return openInterestParams; 286 | | } 287 | | 288 | | // @dev get position fees 289 | | // @param dataStore DataStore 290 | | // @param referralStorage IReferralStorage 291 | | // @param position the position values 292 | | // @param collateralTokenPrice the price of the position's collateralToken 293 | | // @param longToken the long token of the market 294 | | // @param shortToken the short token of the market 295 | | // @param sizeDeltaUsd the change in position size 296 | | // @return PositionFees 297 | * | function getPositionFees( 298 | | GetPositionFeesParams memory params 299 | * | ) internal view returns (PositionFees memory) { 300 | * | PositionFees memory fees = getPositionFeesAfterReferral( 301 | * | params.dataStore, 302 | * | params.referralStorage, 303 | * | params.collateralTokenPrice, 304 | * | params.forPositiveImpact, 305 | * | params.position.account(), 306 | * | params.position.market(), 307 | * | params.sizeDeltaUsd 308 | | ); 309 | | 310 | * | uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position); 311 | | 312 | * | fees.borrowing = getBorrowingFees( 313 | * | params.dataStore, 314 | * | params.collateralTokenPrice, 315 | * | borrowingFeeUsd 316 | | ); 317 | | 318 | * | fees.feeAmountForPool = fees.positionFeeAmountForPool + fees.borrowing.borrowingFeeAmount - fees.borrowing.borrowingFeeAmountForFeeReceiver; 319 | * | fees.feeReceiverAmount += fees.borrowing.borrowingFeeAmountForFeeReceiver; 320 | | 321 | * | fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize( 322 | * | params.dataStore, 323 | * | params.position.market(), 324 | * | params.position.collateralToken(), 325 | * | params.position.isLong() 326 | | ); 327 | | 328 | * | fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize( 329 | * | params.dataStore, 330 | * | params.position.market(), 331 | * | params.longToken, 332 | * | params.position.isLong() 333 | | ); 334 | | 335 | * | fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize( 336 | * | params.dataStore, 337 | * | params.position.market(), 338 | * | params.shortToken, 339 | * | params.position.isLong() 340 | | ); 341 | | 342 | * | fees.funding = getFundingFees( 343 | * | fees.funding, 344 | * | params.position 345 | | ); 346 | | 347 | * | fees.ui = getUiFees( 348 | * | params.dataStore, 349 | * | params.collateralTokenPrice, 350 | * | params.sizeDeltaUsd, 351 | * | params.uiFeeReceiver 352 | | ); 353 | | 354 | * | fees.totalCostAmountExcludingFunding = 355 | * | fees.positionFeeAmount 356 | * | + fees.borrowing.borrowingFeeAmount 357 | * | + fees.ui.uiFeeAmount 358 | * | - fees.referral.traderDiscountAmount; 359 | | 360 | * | fees.totalCostAmount = 361 | * | fees.totalCostAmountExcludingFunding 362 | * | + fees.funding.fundingFeeAmount; 363 | | 364 | * | return fees; 365 | | } 366 | | 367 | * | function getBorrowingFees( 368 | | DataStore dataStore, 369 | | Price.Props memory collateralTokenPrice, 370 | | uint256 borrowingFeeUsd 371 | * | ) internal view returns (PositionBorrowingFees memory) { 372 | * | PositionBorrowingFees memory borrowingFees; 373 | | 374 | * | borrowingFees.borrowingFeeUsd = borrowingFeeUsd; 375 | * | borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min; 376 | * | borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR); 377 | * | borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor); 378 | | 379 | * | return borrowingFees; 380 | | } 381 | | 382 | * | function getFundingFees( 383 | | PositionFundingFees memory fundingFees, 384 | | Position.Props memory position 385 | * | ) internal pure returns (PositionFundingFees memory) { 386 | * | fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount( 387 | * | fundingFees.latestFundingFeeAmountPerSize, 388 | * | position.fundingFeeAmountPerSize(), 389 | * | position.sizeInUsd(), 390 | * | true // roundUpMagnitude 391 | | ); 392 | | 393 | * | fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount( 394 | * | fundingFees.latestLongTokenClaimableFundingAmountPerSize, 395 | * | position.longTokenClaimableFundingAmountPerSize(), 396 | * | position.sizeInUsd(), 397 | * | false // roundUpMagnitude 398 | | ); 399 | | 400 | * | fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount( 401 | * | fundingFees.latestShortTokenClaimableFundingAmountPerSize, 402 | * | position.shortTokenClaimableFundingAmountPerSize(), 403 | * | position.sizeInUsd(), 404 | * | false // roundUpMagnitude 405 | | ); 406 | | 407 | * | return fundingFees; 408 | | } 409 | | 410 | * | function getUiFees( 411 | | DataStore dataStore, 412 | | Price.Props memory collateralTokenPrice, 413 | | uint256 sizeDeltaUsd, 414 | | address uiFeeReceiver 415 | * | ) internal view returns (PositionUiFees memory) { 416 | * | PositionUiFees memory uiFees; 417 | | 418 | * | if (uiFeeReceiver == address(0)) { 419 | * | return uiFees; 420 | | } 421 | | 422 | | uiFees.uiFeeReceiver = uiFeeReceiver; 423 | | uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver); 424 | | uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min; 425 | | 426 | | return uiFees; 427 | | } 428 | | 429 | | // @dev get position fees after applying referral rebates / discounts 430 | | // @param dataStore DataStore 431 | | // @param referralStorage IReferralStorage 432 | | // @param collateralTokenPrice the price of the position's collateralToken 433 | | // @param the position's account 434 | | // @param market the position's market 435 | | // @param sizeDeltaUsd the change in position size 436 | | // @return (affiliate, traderDiscountAmount, affiliateRewardAmount, feeReceiverAmount, positionFeeAmountForPool) 437 | * | function getPositionFeesAfterReferral( 438 | | DataStore dataStore, 439 | | IReferralStorage referralStorage, 440 | | Price.Props memory collateralTokenPrice, 441 | | bool forPositiveImpact, 442 | | address account, 443 | | address market, 444 | | uint256 sizeDeltaUsd 445 | * | ) internal view returns (PositionFees memory) { 446 | * | PositionFees memory fees; 447 | | 448 | * | fees.collateralTokenPrice = collateralTokenPrice; 449 | | 450 | * | fees.referral.trader = account; 451 | | 452 | * | ( 453 | * | fees.referral.referralCode, 454 | * | fees.referral.affiliate, 455 | * | fees.referral.totalRebateFactor, 456 | * | fees.referral.traderDiscountFactor 457 | * | ) = ReferralUtils.getReferralInfo(referralStorage, account); 458 | | 459 | | // note that since it is possible to incur both positive and negative price impact values 460 | | // and the negative price impact factor may be larger than the positive impact factor 461 | | // it is possible for the balance to be improved overall but for the price impact to still be negative 462 | | // in this case the fee factor for the negative price impact would be charged 463 | | // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue 464 | * | fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, forPositiveImpact)); 465 | * | fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min; 466 | | 467 | * | fees.referral.totalRebateAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.totalRebateFactor); 468 | * | fees.referral.traderDiscountAmount = Precision.applyFactor(fees.referral.totalRebateAmount, fees.referral.traderDiscountFactor); 469 | * | fees.referral.affiliateRewardAmount = fees.referral.totalRebateAmount - fees.referral.traderDiscountAmount; 470 | | 471 | * | fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.totalRebateAmount; 472 | | 473 | * | fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR); 474 | * | fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor); 475 | * | fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount; 476 | | 477 | * | return fees; 478 | | } 479 | | 480 | | } 481 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/PricingUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "prb-math/contracts/PRBMathUD60x18.sol"; 6 | | 7 | | import "../utils/Calc.sol"; 8 | | import "../utils/Precision.sol"; 9 | | import "../market/MarketUtils.sol"; 10 | | 11 | | // @title PricingUtils 12 | | // @dev Library for pricing functions 13 | | // 14 | | // Price impact is calculated as: 15 | | // 16 | | // ``` 17 | | // (initial imbalance) ^ (price impact exponent) * (price impact factor / 2) - (next imbalance) ^ (price impact exponent) * (price impact factor / 2) 18 | | // ``` 19 | | // 20 | | // For spot actions (deposits, withdrawals, swaps), imbalance is calculated as the 21 | | // difference in the worth of the long tokens and short tokens. 22 | | // 23 | | // For example: 24 | | // 25 | | // - A pool has 10 long tokens, each long token is worth $5000 26 | | // - The pool also has 50,000 short tokens, each short token is worth $1 27 | | // - The `price impact exponent` is set to 2 and `price impact factor` is set 28 | | // to `0.01 / 50,000` 29 | | // - The pool is equally balanced with $50,000 of long tokens and $50,000 of 30 | | // short tokens 31 | | // - If a user deposits 10 long tokens, the pool would now have $100,000 of long 32 | | // tokens and $50,000 of short tokens 33 | | // - The change in imbalance would be from $0 to -$50,000 34 | | // - There would be negative price impact charged on the user's deposit, 35 | | // calculated as `0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500` 36 | | // - If the user now withdraws 5 long tokens, the balance would change 37 | | // from -$50,000 to -$25,000, a net change of +$25,000 38 | | // - There would be a positive price impact rebated to the user in the form of 39 | | // additional long tokens, calculated as `50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375` 40 | | // 41 | | // For position actions (increase / decrease position), imbalance is calculated 42 | | // as the difference in the long and short open interest. 43 | | // 44 | | // `price impact exponents` and `price impact factors` are configured per market 45 | | // and can differ for spot and position actions. 46 | | // 47 | | // The purpose of the price impact is to help reduce the risk of price manipulation, 48 | | // since the contracts use an oracle price which would be an average or median price 49 | | // of multiple reference exchanges. Without a price impact, it may be profitable to 50 | | // manipulate the prices on reference exchanges while executing orders on the contracts. 51 | | // 52 | | // This risk will also be present if the positive and negative price impact values 53 | | // are similar, for that reason the positive price impact should be set to a low 54 | | // value in times of volatility or irregular price movements. 55 | * | library PricingUtils { 56 | | // @dev get the price impact USD if there is no crossover in balance 57 | | // a crossover in balance is for example if the long open interest is larger 58 | | // than the short open interest, and a short position is opened such that the 59 | | // short open interest becomes larger than the long open interest 60 | | // @param initialDiffUsd the initial difference in USD 61 | | // @param nextDiffUsd the next difference in USD 62 | | // @param impactFactor the impact factor 63 | | // @param impactExponentFactor the impact exponent factor 64 | * | function getPriceImpactUsdForSameSideRebalance( 65 | | uint256 initialDiffUsd, 66 | | uint256 nextDiffUsd, 67 | | uint256 impactFactor, 68 | | uint256 impactExponentFactor 69 | * | ) internal pure returns (int256) { 70 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd; 71 | | 72 | * | uint256 deltaDiffUsd = Calc.diff( 73 | * | applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor), 74 | * | applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor) 75 | | ); 76 | | 77 | * | int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, hasPositiveImpact); 78 | | 79 | * | return priceImpactUsd; 80 | | } 81 | | 82 | | // @dev get the price impact USD if there is a crossover in balance 83 | | // a crossover in balance is for example if the long open interest is larger 84 | | // than the short open interest, and a short position is opened such that the 85 | | // short open interest becomes larger than the long open interest 86 | | // @param initialDiffUsd the initial difference in USD 87 | | // @param nextDiffUsd the next difference in USD 88 | | // @param hasPositiveImpact whether there is a positive impact on balance 89 | | // @param impactFactor the impact factor 90 | | // @param impactExponentFactor the impact exponent factor 91 | * | function getPriceImpactUsdForCrossoverRebalance( 92 | | uint256 initialDiffUsd, 93 | | uint256 nextDiffUsd, 94 | | uint256 positiveImpactFactor, 95 | | uint256 negativeImpactFactor, 96 | | uint256 impactExponentFactor 97 | * | ) internal pure returns (int256) { 98 | * | uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor); 99 | * | uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor); 100 | * | uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd); 101 | | 102 | * | int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd); 103 | | 104 | * | return priceImpactUsd; 105 | | } 106 | | 107 | | // @dev apply the impact factor calculation to a USD diff value 108 | | // @param diffUsd the difference in USD 109 | | // @param impactFactor the impact factor 110 | | // @param impactExponentFactor the impact exponent factor 111 | * | function applyImpactFactor( 112 | | uint256 diffUsd, 113 | | uint256 impactFactor, 114 | | uint256 impactExponentFactor 115 | * | ) internal pure returns (uint256) { 116 | * | uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor); 117 | * | return Precision.applyFactor(exponentValue, impactFactor); 118 | | } 119 | | } 120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/pricing/SwapPricingUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../market/MarketUtils.sol"; 8 | | 9 | | import "../utils/Precision.sol"; 10 | | import "../utils/Calc.sol"; 11 | | 12 | | import "./PricingUtils.sol"; 13 | | import "./ISwapPricingUtils.sol"; 14 | | 15 | | // @title SwapPricingUtils 16 | | // @dev Library for pricing functions 17 | * | library SwapPricingUtils { 18 | | using SignedMath for int256; 19 | | using SafeCast for uint256; 20 | | using SafeCast for int256; 21 | | 22 | | using EventUtils for EventUtils.AddressItems; 23 | | using EventUtils for EventUtils.UintItems; 24 | | using EventUtils for EventUtils.IntItems; 25 | | using EventUtils for EventUtils.BoolItems; 26 | | using EventUtils for EventUtils.Bytes32Items; 27 | | using EventUtils for EventUtils.BytesItems; 28 | | using EventUtils for EventUtils.StringItems; 29 | | 30 | | // @dev GetPriceImpactUsdParams struct used in getPriceImpactUsd to 31 | | // avoid stack too deep errors 32 | | // @param dataStore DataStore 33 | | // @param market the market to check 34 | | // @param tokenA the token to check balance for 35 | | // @param tokenB the token to check balance for 36 | | // @param priceForTokenA the price for tokenA 37 | | // @param priceForTokenB the price for tokenB 38 | | // @param usdDeltaForTokenA the USD change in amount of tokenA 39 | | // @param usdDeltaForTokenB the USD change in amount of tokenB 40 | | struct GetPriceImpactUsdParams { 41 | | DataStore dataStore; 42 | | Market.Props market; 43 | | address tokenA; 44 | | address tokenB; 45 | | uint256 priceForTokenA; 46 | | uint256 priceForTokenB; 47 | | int256 usdDeltaForTokenA; 48 | | int256 usdDeltaForTokenB; 49 | | bool includeVirtualInventoryImpact; 50 | | } 51 | | 52 | | struct EmitSwapInfoParams { 53 | | bytes32 orderKey; 54 | | address market; 55 | | address receiver; 56 | | address tokenIn; 57 | | address tokenOut; 58 | | uint256 tokenInPrice; 59 | | uint256 tokenOutPrice; 60 | | uint256 amountIn; 61 | | uint256 amountInAfterFees; 62 | | uint256 amountOut; 63 | | int256 priceImpactUsd; 64 | | int256 priceImpactAmount; 65 | | int256 tokenInPriceImpactAmount; 66 | | } 67 | | 68 | | // @dev PoolParams struct to contain pool values 69 | | // @param poolUsdForTokenA the USD value of tokenA in the pool 70 | | // @param poolUsdForTokenB the USD value of tokenB in the pool 71 | | // @param nextPoolUsdForTokenA the next USD value of tokenA in the pool 72 | | // @param nextPoolUsdForTokenB the next USD value of tokenB in the pool 73 | | struct PoolParams { 74 | | uint256 poolUsdForTokenA; 75 | | uint256 poolUsdForTokenB; 76 | | uint256 nextPoolUsdForTokenA; 77 | | uint256 nextPoolUsdForTokenB; 78 | | } 79 | | 80 | | // @dev SwapFees struct to contain swap fee values 81 | | // @param feeReceiverAmount the fee amount for the fee receiver 82 | | // @param feeAmountForPool the fee amount for the pool 83 | | // @param amountAfterFees the output amount after fees 84 | | struct SwapFees { 85 | | uint256 feeReceiverAmount; 86 | | uint256 feeAmountForPool; 87 | | uint256 amountAfterFees; 88 | | 89 | | address uiFeeReceiver; 90 | | uint256 uiFeeReceiverFactor; 91 | | uint256 uiFeeAmount; 92 | | } 93 | | 94 | | // @dev get the price impact in USD 95 | | // 96 | | // note that there will be some difference between the pool amounts used for 97 | | // calculating the price impact and fees vs the actual pool amounts after the 98 | | // swap is done, since the pool amounts will be increased / decreased by an amount 99 | | // after factoring in the calculated price impact and fees 100 | | // 101 | | // since the calculations are based on the real-time prices values of the tokens 102 | | // if a token price increases, the pool will incentivise swapping out more of that token 103 | | // this is useful if prices are ranging, if prices are strongly directional, the pool may 104 | | // be selling tokens as the token price increases 105 | | // 106 | | // @param params GetPriceImpactUsdParams 107 | | // 108 | | // @return the price impact in USD 109 | * | function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) { 110 | * | PoolParams memory poolParams = getNextPoolAmountsUsd(params); 111 | | 112 | * | int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market, poolParams); 113 | | 114 | | // the virtual price impact calculation is skipped if the price impact 115 | | // is positive since the action is helping to balance the pool 116 | | // 117 | | // in case two virtual pools are unbalanced in a different direction 118 | | // e.g. pool0 has more WNT than USDC while pool1 has less WNT 119 | | // than USDT 120 | | // not skipping the virtual price impact calculation would lead to 121 | | // a negative price impact for any trade on either pools and would 122 | | // disincentivise the balancing of pools 123 | * | if (priceImpactUsd >= 0) { return priceImpactUsd; } 124 | | 125 | | if (!params.includeVirtualInventoryImpact) { 126 | | return priceImpactUsd; 127 | | } 128 | | 129 | | // note that the virtual pool for the long token / short token may be different across pools 130 | | // e.g. ETH/USDC, ETH/USDT would have USDC and USDT as the short tokens 131 | | // the short token amount is multiplied by the price of the token in the current pool, e.g. if the swap 132 | | // is for the ETH/USDC pool, the combined USDC and USDT short token amounts is multiplied by the price of 133 | | // USDC to calculate the price impact, this should be reasonable most of the time unless there is a 134 | | // large depeg of one of the tokens, in which case it may be necessary to remove that market from being a virtual 135 | | // market, removal of virtual markets may lead to incorrect virtual token accounting, the feature to correct for 136 | | // this can be added if needed 137 | | (bool hasVirtualInventory, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils.getVirtualInventoryForSwaps( 138 | | params.dataStore, 139 | | params.market.marketToken 140 | | ); 141 | | 142 | | if (!hasVirtualInventory) { 143 | | return priceImpactUsd; 144 | | } 145 | | 146 | | uint256 virtualPoolAmountForTokenA; 147 | | uint256 virtualPoolAmountForTokenB; 148 | | 149 | | if (params.tokenA == params.market.longToken) { 150 | | virtualPoolAmountForTokenA = virtualPoolAmountForLongToken; 151 | | virtualPoolAmountForTokenB = virtualPoolAmountForShortToken; 152 | | } else { 153 | | virtualPoolAmountForTokenA = virtualPoolAmountForShortToken; 154 | | virtualPoolAmountForTokenB = virtualPoolAmountForLongToken; 155 | | } 156 | | 157 | | PoolParams memory poolParamsForVirtualInventory = getNextPoolAmountsParams( 158 | | params, 159 | | virtualPoolAmountForTokenA, 160 | | virtualPoolAmountForTokenB 161 | | ); 162 | | 163 | | int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market, poolParamsForVirtualInventory); 164 | | 165 | | return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd; 166 | | } 167 | | 168 | | // @dev get the price impact in USD 169 | | // @param dataStore DataStore 170 | | // @param market the trading market 171 | | // @param poolParams PoolParams 172 | | // @return the price impact in USD 173 | * | function _getPriceImpactUsd(DataStore dataStore, Market.Props memory market, PoolParams memory poolParams) internal view returns (int256) { 174 | * | uint256 initialDiffUsd = Calc.diff(poolParams.poolUsdForTokenA, poolParams.poolUsdForTokenB); 175 | * | uint256 nextDiffUsd = Calc.diff(poolParams.nextPoolUsdForTokenA, poolParams.nextPoolUsdForTokenB); 176 | | 177 | | // check whether an improvement in balance comes from causing the balance to switch sides 178 | | // for example, if there is $2000 of ETH and $1000 of USDC in the pool 179 | | // adding $1999 USDC into the pool will reduce absolute balance from $1000 to $999 but it does not 180 | | // help rebalance the pool much, the isSameSideRebalance value helps avoid gaming using this case 181 | * | bool isSameSideRebalance = (poolParams.poolUsdForTokenA <= poolParams.poolUsdForTokenB) == (poolParams.nextPoolUsdForTokenA <= poolParams.nextPoolUsdForTokenB); 182 | * | uint256 impactExponentFactor = dataStore.getUint(Keys.swapImpactExponentFactorKey(market.marketToken)); 183 | | 184 | * | if (isSameSideRebalance) { 185 | * | bool hasPositiveImpact = nextDiffUsd < initialDiffUsd; 186 | * | uint256 impactFactor = MarketUtils.getAdjustedSwapImpactFactor(dataStore, market.marketToken, hasPositiveImpact); 187 | | 188 | * | return PricingUtils.getPriceImpactUsdForSameSideRebalance( 189 | * | initialDiffUsd, 190 | * | nextDiffUsd, 191 | * | impactFactor, 192 | * | impactExponentFactor 193 | | ); 194 | | } else { 195 | * | (uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedSwapImpactFactors(dataStore, market.marketToken); 196 | | 197 | * | return PricingUtils.getPriceImpactUsdForCrossoverRebalance( 198 | * | initialDiffUsd, 199 | * | nextDiffUsd, 200 | * | positiveImpactFactor, 201 | * | negativeImpactFactor, 202 | * | impactExponentFactor 203 | | ); 204 | | } 205 | | } 206 | | 207 | | // @dev get the next pool amounts in USD 208 | | // @param params GetPriceImpactUsdParams 209 | | // @return PoolParams 210 | * | function getNextPoolAmountsUsd( 211 | | GetPriceImpactUsdParams memory params 212 | * | ) internal view returns (PoolParams memory) { 213 | * | uint256 poolAmountForTokenA = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenA); 214 | * | uint256 poolAmountForTokenB = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenB); 215 | | 216 | * | return getNextPoolAmountsParams( 217 | * | params, 218 | * | poolAmountForTokenA, 219 | * | poolAmountForTokenB 220 | | ); 221 | | } 222 | | 223 | * | function getNextPoolAmountsParams( 224 | | GetPriceImpactUsdParams memory params, 225 | | uint256 poolAmountForTokenA, 226 | | uint256 poolAmountForTokenB 227 | * | ) internal pure returns (PoolParams memory) { 228 | * | uint256 poolUsdForTokenA = poolAmountForTokenA * params.priceForTokenA; 229 | * | uint256 poolUsdForTokenB = poolAmountForTokenB * params.priceForTokenB; 230 | | 231 | * | if (params.usdDeltaForTokenA < 0 && (-params.usdDeltaForTokenA).toUint256() > poolUsdForTokenA) { 232 | | revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenA, poolUsdForTokenA); 233 | | } 234 | | 235 | * | if (params.usdDeltaForTokenB < 0 && (-params.usdDeltaForTokenB).toUint256() > poolUsdForTokenB) { 236 | * | revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenB, poolUsdForTokenB); 237 | | } 238 | | 239 | * | uint256 nextPoolUsdForTokenA = Calc.sumReturnUint256(poolUsdForTokenA, params.usdDeltaForTokenA); 240 | * | uint256 nextPoolUsdForTokenB = Calc.sumReturnUint256(poolUsdForTokenB, params.usdDeltaForTokenB); 241 | | 242 | * | PoolParams memory poolParams = PoolParams( 243 | * | poolUsdForTokenA, 244 | * | poolUsdForTokenB, 245 | * | nextPoolUsdForTokenA, 246 | * | nextPoolUsdForTokenB 247 | | ); 248 | | 249 | * | return poolParams; 250 | | } 251 | | 252 | | // @dev get the swap fees 253 | | // @param dataStore DataStore 254 | | // @param marketToken the address of the market token 255 | | // @param amount the total swap fee amount 256 | * | function getSwapFees( 257 | | DataStore dataStore, 258 | | address marketToken, 259 | | uint256 amount, 260 | | bool forPositiveImpact, 261 | | address uiFeeReceiver, 262 | | ISwapPricingUtils.SwapPricingType swapPricingType 263 | * | ) internal view returns (SwapFees memory) { 264 | * | SwapFees memory fees; 265 | | 266 | | // note that since it is possible to incur both positive and negative price impact values 267 | | // and the negative price impact factor may be larger than the positive impact factor 268 | | // it is possible for the balance to be improved overall but for the price impact to still be negative 269 | | // in this case the fee factor for the negative price impact would be charged 270 | | // a user could split the order into two, to incur a smaller fee, reducing the fee through this should not be a large issue 271 | * | uint256 feeFactor; 272 | | 273 | * | if (swapPricingType == ISwapPricingUtils.SwapPricingType.TwoStep) { 274 | * | feeFactor = dataStore.getUint(Keys.swapFeeFactorKey(marketToken, forPositiveImpact)); 275 | * | } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Shift) { 276 | | // empty branch as feeFactor is already zero 277 | * | } else if (swapPricingType == ISwapPricingUtils.SwapPricingType.Atomic) { 278 | * | feeFactor = dataStore.getUint(Keys.atomicSwapFeeFactorKey(marketToken)); 279 | | } 280 | | 281 | * | uint256 swapFeeReceiverFactor = dataStore.getUint(Keys.SWAP_FEE_RECEIVER_FACTOR); 282 | | 283 | * | uint256 feeAmount = Precision.applyFactor(amount, feeFactor); 284 | | 285 | * | fees.feeReceiverAmount = Precision.applyFactor(feeAmount, swapFeeReceiverFactor); 286 | * | fees.feeAmountForPool = feeAmount - fees.feeReceiverAmount; 287 | | 288 | * | fees.uiFeeReceiver = uiFeeReceiver; 289 | * | fees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver); 290 | * | fees.uiFeeAmount = Precision.applyFactor(amount, fees.uiFeeReceiverFactor); 291 | | 292 | * | fees.amountAfterFees = amount - feeAmount - fees.uiFeeAmount; 293 | | 294 | * | return fees; 295 | | } 296 | | 297 | | // note that the priceImpactUsd may not be entirely accurate since it is the 298 | | // base calculation and the actual price impact may be capped by the available 299 | | // amount in the swap impact pool 300 | * | function emitSwapInfo( 301 | | EventEmitter eventEmitter, 302 | | EmitSwapInfoParams memory params 303 | * | ) internal { 304 | * | EventUtils.EventLogData memory eventData; 305 | | 306 | * | eventData.bytes32Items.initItems(1); 307 | * | eventData.bytes32Items.setItem(0, "orderKey", params.orderKey); 308 | | 309 | * | eventData.addressItems.initItems(4); 310 | * | eventData.addressItems.setItem(0, "market", params.market); 311 | * | eventData.addressItems.setItem(1, "receiver", params.receiver); 312 | * | eventData.addressItems.setItem(2, "tokenIn", params.tokenIn); 313 | * | eventData.addressItems.setItem(3, "tokenOut", params.tokenOut); 314 | | 315 | * | eventData.uintItems.initItems(5); 316 | * | eventData.uintItems.setItem(0, "tokenInPrice", params.tokenInPrice); 317 | * | eventData.uintItems.setItem(1, "tokenOutPrice", params.tokenOutPrice); 318 | * | eventData.uintItems.setItem(2, "amountIn", params.amountIn); 319 | | // note that amountInAfterFees includes negative price impact 320 | * | eventData.uintItems.setItem(3, "amountInAfterFees", params.amountInAfterFees); 321 | * | eventData.uintItems.setItem(4, "amountOut", params.amountOut); 322 | | 323 | * | eventData.intItems.initItems(3); 324 | * | eventData.intItems.setItem(0, "priceImpactUsd", params.priceImpactUsd); 325 | * | eventData.intItems.setItem(1, "priceImpactAmount", params.priceImpactAmount); 326 | * | eventData.intItems.setItem(2, "tokenInPriceImpactAmount", params.tokenInPriceImpactAmount); 327 | | 328 | * | eventEmitter.emitEventLog1( 329 | | "SwapInfo", 330 | * | Cast.toBytes32(params.market), 331 | * | eventData 332 | | ); 333 | | } 334 | | 335 | * | function emitSwapFeesCollected( 336 | | EventEmitter eventEmitter, 337 | | bytes32 tradeKey, 338 | | address market, 339 | | address token, 340 | | uint256 tokenPrice, 341 | | bytes32 swapFeeType, 342 | | SwapFees memory fees 343 | * | ) internal { 344 | * | EventUtils.EventLogData memory eventData; 345 | | 346 | * | eventData.bytes32Items.initItems(2); 347 | * | eventData.bytes32Items.setItem(0, "tradeKey", tradeKey); 348 | * | eventData.bytes32Items.setItem(1, "swapFeeType", swapFeeType); 349 | | 350 | * | eventData.addressItems.initItems(3); 351 | * | eventData.addressItems.setItem(0, "uiFeeReceiver", fees.uiFeeReceiver); 352 | * | eventData.addressItems.setItem(1, "market", market); 353 | * | eventData.addressItems.setItem(2, "token", token); 354 | | 355 | * | eventData.uintItems.initItems(6); 356 | * | eventData.uintItems.setItem(0, "tokenPrice", tokenPrice); 357 | * | eventData.uintItems.setItem(1, "feeReceiverAmount", fees.feeReceiverAmount); 358 | * | eventData.uintItems.setItem(2, "feeAmountForPool", fees.feeAmountForPool); 359 | * | eventData.uintItems.setItem(3, "amountAfterFees", fees.amountAfterFees); 360 | * | eventData.uintItems.setItem(4, "uiFeeReceiverFactor", fees.uiFeeReceiverFactor); 361 | * | eventData.uintItems.setItem(5, "uiFeeAmount", fees.uiFeeAmount); 362 | | 363 | * | eventEmitter.emitEventLog1( 364 | | "SwapFeesCollected", 365 | * | Cast.toBytes32(market), 366 | * | eventData 367 | | ); 368 | | } 369 | | } 370 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/Reader.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | 7 | | import "../market/MarketStoreUtils.sol"; 8 | | 9 | | import "../deposit/DepositStoreUtils.sol"; 10 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 11 | | import "../shift/ShiftStoreUtils.sol"; 12 | | 13 | | import "../position/Position.sol"; 14 | | import "../position/PositionUtils.sol"; 15 | | import "../position/PositionStoreUtils.sol"; 16 | | 17 | | import "../order/OrderStoreUtils.sol"; 18 | | 19 | | import "../market/MarketUtils.sol"; 20 | | import "../market/Market.sol"; 21 | | 22 | | import "../adl/AdlUtils.sol"; 23 | | 24 | | import "./ReaderUtils.sol"; 25 | | import "./ReaderDepositUtils.sol"; 26 | | import "./ReaderWithdrawalUtils.sol"; 27 | | 28 | | // @title Reader 29 | | // @dev Library for read functions 30 | * | contract Reader { 31 | | using SafeCast for uint256; 32 | | using Position for Position.Props; 33 | | 34 | * | function getMarket(DataStore dataStore, address key) external view returns (Market.Props memory) { 35 | * | return MarketStoreUtils.get(dataStore, key); 36 | | } 37 | | 38 | | function getMarketBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) { 39 | | return MarketStoreUtils.getBySalt(dataStore, salt); 40 | | } 41 | | 42 | | function getDeposit(DataStore dataStore, bytes32 key) external view returns (Deposit.Props memory) { 43 | | return DepositStoreUtils.get(dataStore, key); 44 | | } 45 | | 46 | * | function getWithdrawal(DataStore dataStore, bytes32 key) external view returns (Withdrawal.Props memory) { 47 | * | return WithdrawalStoreUtils.get(dataStore, key); 48 | | } 49 | | 50 | | function getShift(DataStore dataStore, bytes32 key) external view returns (Shift.Props memory) { 51 | | return ShiftStoreUtils.get(dataStore, key); 52 | | } 53 | | 54 | | function getPosition(DataStore dataStore, bytes32 key) external view returns (Position.Props memory) { 55 | | return PositionStoreUtils.get(dataStore, key); 56 | | } 57 | | 58 | | function getOrder(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) { 59 | | return OrderStoreUtils.get(dataStore, key); 60 | | } 61 | | 62 | | function getPositionPnlUsd( 63 | | DataStore dataStore, 64 | | Market.Props memory market, 65 | | MarketUtils.MarketPrices memory prices, 66 | | bytes32 positionKey, 67 | | uint256 sizeDeltaUsd 68 | | ) external view returns (int256, int256, uint256) { 69 | | Position.Props memory position = PositionStoreUtils.get(dataStore, positionKey); 70 | | 71 | | return PositionUtils.getPositionPnlUsd(dataStore, market, prices, position, sizeDeltaUsd); 72 | | } 73 | | 74 | * | function getAccountPositions( 75 | | DataStore dataStore, 76 | | address account, 77 | | uint256 start, 78 | | uint256 end 79 | * | ) external view returns (Position.Props[] memory) { 80 | * | bytes32[] memory positionKeys = PositionStoreUtils.getAccountPositionKeys(dataStore, account, start, end); 81 | * | Position.Props[] memory positions = new Position.Props[](positionKeys.length); 82 | * | for (uint256 i; i < positionKeys.length; i++) { 83 | * | bytes32 positionKey = positionKeys[i]; 84 | * | positions[i] = PositionStoreUtils.get(dataStore, positionKey); 85 | | } 86 | | 87 | * | return positions; 88 | | } 89 | | 90 | | function getAccountPositionInfoList( 91 | | DataStore dataStore, 92 | | IReferralStorage referralStorage, 93 | | bytes32[] memory positionKeys, 94 | | MarketUtils.MarketPrices[] memory prices, 95 | | address uiFeeReceiver 96 | | ) external view returns (ReaderUtils.PositionInfo[] memory) { 97 | | ReaderUtils.PositionInfo[] memory positionInfoList = new ReaderUtils.PositionInfo[](positionKeys.length); 98 | | for (uint256 i; i < positionKeys.length; i++) { 99 | | bytes32 positionKey = positionKeys[i]; 100 | | positionInfoList[i] = getPositionInfo( 101 | | dataStore, 102 | | referralStorage, 103 | | positionKey, 104 | | prices[i], 105 | | 0, // sizeDeltaUsd 106 | | uiFeeReceiver, 107 | | true // usePositionSizeAsSizeDeltaUsd 108 | | ); 109 | | } 110 | | 111 | | return positionInfoList; 112 | | } 113 | | 114 | * | function getPositionInfo( 115 | | DataStore dataStore, 116 | | IReferralStorage referralStorage, 117 | | bytes32 positionKey, 118 | | MarketUtils.MarketPrices memory prices, 119 | | uint256 sizeDeltaUsd, 120 | | address uiFeeReceiver, 121 | | bool usePositionSizeAsSizeDeltaUsd 122 | * | ) public view returns (ReaderUtils.PositionInfo memory) { 123 | * | return 124 | * | ReaderUtils.getPositionInfo( 125 | * | dataStore, 126 | * | referralStorage, 127 | * | positionKey, 128 | * | prices, 129 | * | sizeDeltaUsd, 130 | * | uiFeeReceiver, 131 | * | usePositionSizeAsSizeDeltaUsd 132 | | ); 133 | | } 134 | | 135 | | function getAccountOrders( 136 | | DataStore dataStore, 137 | | address account, 138 | | uint256 start, 139 | | uint256 end 140 | | ) external view returns (Order.Props[] memory) { 141 | | bytes32[] memory orderKeys = OrderStoreUtils.getAccountOrderKeys(dataStore, account, start, end); 142 | | Order.Props[] memory orders = new Order.Props[](orderKeys.length); 143 | | for (uint256 i; i < orderKeys.length; i++) { 144 | | bytes32 orderKey = orderKeys[i]; 145 | | orders[i] = OrderStoreUtils.get(dataStore, orderKey); 146 | | } 147 | | 148 | | return orders; 149 | | } 150 | | 151 | | function getMarkets(DataStore dataStore, uint256 start, uint256 end) external view returns (Market.Props[] memory) { 152 | | address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end); 153 | | Market.Props[] memory markets = new Market.Props[](marketKeys.length); 154 | | for (uint256 i; i < marketKeys.length; i++) { 155 | | address marketKey = marketKeys[i]; 156 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey); 157 | | markets[i] = market; 158 | | } 159 | | 160 | | return markets; 161 | | } 162 | | 163 | | function getMarketInfoList( 164 | | DataStore dataStore, 165 | | MarketUtils.MarketPrices[] memory marketPricesList, 166 | | uint256 start, 167 | | uint256 end 168 | | ) external view returns (ReaderUtils.MarketInfo[] memory) { 169 | | address[] memory marketKeys = MarketStoreUtils.getMarketKeys(dataStore, start, end); 170 | | ReaderUtils.MarketInfo[] memory marketInfoList = new ReaderUtils.MarketInfo[](marketKeys.length); 171 | | for (uint256 i; i < marketKeys.length; i++) { 172 | | MarketUtils.MarketPrices memory prices = marketPricesList[i]; 173 | | address marketKey = marketKeys[i]; 174 | | marketInfoList[i] = getMarketInfo(dataStore, prices, marketKey); 175 | | } 176 | | 177 | | return marketInfoList; 178 | | } 179 | | 180 | * | function getMarketInfo( 181 | | DataStore dataStore, 182 | | MarketUtils.MarketPrices memory prices, 183 | | address marketKey 184 | * | ) public view returns (ReaderUtils.MarketInfo memory) { 185 | * | return ReaderUtils.getMarketInfo( 186 | * | dataStore, 187 | * | prices, 188 | * | marketKey 189 | | ); 190 | | } 191 | | 192 | | function getMarketTokenPrice( 193 | | DataStore dataStore, 194 | | Market.Props memory market, 195 | | Price.Props memory indexTokenPrice, 196 | | Price.Props memory longTokenPrice, 197 | | Price.Props memory shortTokenPrice, 198 | | bytes32 pnlFactorType, 199 | | bool maximize 200 | | ) external view returns (int256, MarketPoolValueInfo.Props memory) { 201 | | return 202 | | MarketUtils.getMarketTokenPrice( 203 | | dataStore, 204 | | market, 205 | | indexTokenPrice, 206 | | longTokenPrice, 207 | | shortTokenPrice, 208 | | pnlFactorType, 209 | | maximize 210 | | ); 211 | | } 212 | | 213 | | function getNetPnl( 214 | | DataStore dataStore, 215 | | Market.Props memory market, 216 | | Price.Props memory indexTokenPrice, 217 | | bool maximize 218 | | ) external view returns (int256) { 219 | | return MarketUtils.getNetPnl(dataStore, market, indexTokenPrice, maximize); 220 | | } 221 | | 222 | | function getPnl( 223 | | DataStore dataStore, 224 | | Market.Props memory market, 225 | | Price.Props memory indexTokenPrice, 226 | | bool isLong, 227 | | bool maximize 228 | | ) external view returns (int256) { 229 | | return MarketUtils.getPnl(dataStore, market, indexTokenPrice, isLong, maximize); 230 | | } 231 | | 232 | | function getOpenInterestWithPnl( 233 | | DataStore dataStore, 234 | | Market.Props memory market, 235 | | Price.Props memory indexTokenPrice, 236 | | bool isLong, 237 | | bool maximize 238 | | ) external view returns (int256) { 239 | | return MarketUtils.getOpenInterestWithPnl(dataStore, market, indexTokenPrice, isLong, maximize); 240 | | } 241 | | 242 | | function getPnlToPoolFactor( 243 | | DataStore dataStore, 244 | | address marketAddress, 245 | | MarketUtils.MarketPrices memory prices, 246 | | bool isLong, 247 | | bool maximize 248 | | ) external view returns (int256) { 249 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress); 250 | | return MarketUtils.getPnlToPoolFactor(dataStore, market, prices, isLong, maximize); 251 | | } 252 | | 253 | * | function getSwapAmountOut( 254 | | DataStore dataStore, 255 | | Market.Props memory market, 256 | | MarketUtils.MarketPrices memory prices, 257 | | address tokenIn, 258 | | uint256 amountIn, 259 | | address uiFeeReceiver 260 | * | ) external view returns (uint256, int256, SwapPricingUtils.SwapFees memory fees) { 261 | * | return ReaderPricingUtils.getSwapAmountOut(dataStore, market, prices, tokenIn, amountIn, uiFeeReceiver); 262 | | } 263 | | 264 | | function getExecutionPrice( 265 | | DataStore dataStore, 266 | | address marketKey, 267 | | Price.Props memory indexTokenPrice, 268 | | uint256 positionSizeInUsd, 269 | | uint256 positionSizeInTokens, 270 | | int256 sizeDeltaUsd, 271 | | bool isLong 272 | | ) external view returns (ReaderPricingUtils.ExecutionPriceResult memory) { 273 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey); 274 | | return 275 | | ReaderPricingUtils.getExecutionPrice( 276 | | dataStore, 277 | | market, 278 | | indexTokenPrice, 279 | | positionSizeInUsd, 280 | | positionSizeInTokens, 281 | | sizeDeltaUsd, 282 | | isLong 283 | | ); 284 | | } 285 | | 286 | | function getSwapPriceImpact( 287 | | DataStore dataStore, 288 | | address marketKey, 289 | | address tokenIn, 290 | | address tokenOut, 291 | | uint256 amountIn, 292 | | Price.Props memory tokenInPrice, 293 | | Price.Props memory tokenOutPrice 294 | | ) external view returns (int256, int256, int256) { 295 | | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey); 296 | | return 297 | | ReaderPricingUtils.getSwapPriceImpact( 298 | | dataStore, 299 | | market, 300 | | tokenIn, 301 | | tokenOut, 302 | | amountIn, 303 | | tokenInPrice, 304 | | tokenOutPrice 305 | | ); 306 | | } 307 | | 308 | | function getAdlState( 309 | | DataStore dataStore, 310 | | address market, 311 | | bool isLong, 312 | | MarketUtils.MarketPrices memory prices 313 | | ) external view returns (uint256, bool, int256, uint256) { 314 | | uint256 latestAdlTime = AdlUtils.getLatestAdlTime(dataStore, market, isLong); 315 | | Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market); 316 | | 317 | | (bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded( 318 | | dataStore, 319 | | _market, 320 | | prices, 321 | | isLong, 322 | | Keys.MAX_PNL_FACTOR_FOR_ADL 323 | | ); 324 | | 325 | | return (latestAdlTime, shouldEnableAdl, pnlToPoolFactor, maxPnlFactor); 326 | | } 327 | | 328 | | function getDepositAmountOut( 329 | | DataStore dataStore, 330 | | Market.Props memory market, 331 | | MarketUtils.MarketPrices memory prices, 332 | | uint256 longTokenAmount, 333 | | uint256 shortTokenAmount, 334 | | address uiFeeReceiver, 335 | | ISwapPricingUtils.SwapPricingType swapPricingType, 336 | | bool includeVirtualInventoryImpact 337 | | ) external view returns (uint256) { 338 | | return ReaderDepositUtils.getDepositAmountOut( 339 | | dataStore, 340 | | market, 341 | | prices, 342 | | longTokenAmount, 343 | | shortTokenAmount, 344 | | uiFeeReceiver, 345 | | swapPricingType, 346 | | includeVirtualInventoryImpact 347 | | ); 348 | | } 349 | | 350 | | function getWithdrawalAmountOut( 351 | | DataStore dataStore, 352 | | Market.Props memory market, 353 | | MarketUtils.MarketPrices memory prices, 354 | | uint256 marketTokenAmount, 355 | | address uiFeeReceiver, 356 | | ISwapPricingUtils.SwapPricingType swapPricingType 357 | | ) external view returns (uint256, uint256) { 358 | | return ReaderWithdrawalUtils.getWithdrawalAmountOut( 359 | | dataStore, 360 | | market, 361 | | prices, 362 | | marketTokenAmount, 363 | | uiFeeReceiver, 364 | | swapPricingType 365 | | ); 366 | | } 367 | | } 368 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderDepositUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "../market/MarketStoreUtils.sol"; 10 | | 11 | | import "../deposit/DepositStoreUtils.sol"; 12 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 13 | | 14 | | import "../position/Position.sol"; 15 | | import "../position/PositionUtils.sol"; 16 | | import "../position/PositionStoreUtils.sol"; 17 | | import "../position/IncreasePositionUtils.sol"; 18 | | import "../position/DecreasePositionUtils.sol"; 19 | | 20 | | import "../order/OrderStoreUtils.sol"; 21 | | 22 | | import "../market/MarketUtils.sol"; 23 | | import "../market/Market.sol"; 24 | | import "./ReaderPricingUtils.sol"; 25 | | 26 | * | library ReaderDepositUtils { 27 | | using SignedMath for int256; 28 | | using SafeCast for uint256; 29 | | using SafeCast for int256; 30 | | using Price for Price.Props; 31 | | using Position for Position.Props; 32 | | using Order for Order.Props; 33 | | 34 | | struct GetDepositAmountOutForSingleTokenParams { 35 | | DataStore dataStore; 36 | | Market.Props market; 37 | | MarketUtils.MarketPrices prices; 38 | | address tokenIn; 39 | | Price.Props tokenInPrice; 40 | | address tokenOut; 41 | | Price.Props tokenOutPrice; 42 | | uint256 amount; 43 | | int256 priceImpactUsd; 44 | | address uiFeeReceiver; 45 | | ISwapPricingUtils.SwapPricingType swapPricingType; 46 | | } 47 | | 48 | * | function getDepositAmountOut( 49 | | DataStore dataStore, 50 | | Market.Props memory market, 51 | | MarketUtils.MarketPrices memory prices, 52 | | uint256 longTokenAmount, 53 | | uint256 shortTokenAmount, 54 | | address uiFeeReceiver, 55 | | ISwapPricingUtils.SwapPricingType swapPricingType, 56 | | bool includeVirtualInventoryImpact 57 | * | ) internal view returns (uint256) { 58 | * | uint256 longTokenUsd = longTokenAmount * prices.longTokenPrice.midPrice(); 59 | * | uint256 shortTokenUsd = shortTokenAmount * prices.shortTokenPrice.midPrice(); 60 | * | int256 priceImpactUsd = SwapPricingUtils.getPriceImpactUsd( 61 | * | SwapPricingUtils.GetPriceImpactUsdParams( 62 | * | dataStore, 63 | * | market, 64 | * | market.longToken, 65 | * | market.shortToken, 66 | * | prices.longTokenPrice.midPrice(), 67 | * | prices.shortTokenPrice.midPrice(), 68 | * | longTokenUsd.toInt256(), 69 | * | shortTokenUsd.toInt256(), 70 | * | includeVirtualInventoryImpact 71 | | ) 72 | | ); 73 | | 74 | * | uint256 mintAmount; 75 | | 76 | * | mintAmount += getDepositAmountOutForSingleToken( 77 | * | GetDepositAmountOutForSingleTokenParams( 78 | * | dataStore, 79 | * | market, 80 | * | prices, 81 | * | market.longToken, 82 | * | prices.longTokenPrice, 83 | * | market.shortToken, 84 | * | prices.shortTokenPrice, 85 | * | longTokenAmount, 86 | * | Precision.mulDiv(priceImpactUsd, longTokenUsd, longTokenUsd + shortTokenUsd), 87 | * | uiFeeReceiver, 88 | * | swapPricingType 89 | | ) 90 | | ); 91 | | 92 | * | mintAmount += getDepositAmountOutForSingleToken( 93 | * | GetDepositAmountOutForSingleTokenParams( 94 | * | dataStore, 95 | * | market, 96 | * | prices, 97 | * | market.shortToken, 98 | * | prices.shortTokenPrice, 99 | * | market.longToken, 100 | * | prices.longTokenPrice, 101 | * | shortTokenAmount, 102 | * | Precision.mulDiv(priceImpactUsd, shortTokenUsd, longTokenUsd + shortTokenUsd), 103 | * | uiFeeReceiver, 104 | * | swapPricingType 105 | | ) 106 | | ); 107 | | 108 | * | return mintAmount; 109 | | } 110 | | 111 | * | function getDepositAmountOutForSingleToken( 112 | | GetDepositAmountOutForSingleTokenParams memory params 113 | * | ) internal view returns (uint256) { 114 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees( 115 | * | params.dataStore, 116 | * | params.market.marketToken, 117 | * | params.amount, 118 | * | params.priceImpactUsd > 0, // forPositiveImpact 119 | * | params.uiFeeReceiver, // uiFeeReceiver 120 | * | params.swapPricingType 121 | | ); 122 | | 123 | * | uint256 mintAmount; 124 | | 125 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 126 | * | params.dataStore, 127 | * | params.market, 128 | * | params.prices.indexTokenPrice, 129 | * | params.prices.longTokenPrice, 130 | * | params.prices.shortTokenPrice, 131 | | Keys.MAX_PNL_FACTOR_FOR_DEPOSITS, 132 | * | true 133 | | ); 134 | | 135 | * | if (poolValueInfo.poolValue < 0) { 136 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue); 137 | | } 138 | | 139 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256(); 140 | | 141 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(params.market.marketToken))); 142 | | 143 | * | if (poolValueInfo.poolValue == 0 && marketTokensSupply > 0) { 144 | | revert Errors.InvalidPoolValueForDeposit(poolValueInfo.poolValue); 145 | | } 146 | | 147 | * | if (params.priceImpactUsd > 0 && marketTokensSupply == 0) { 148 | | params.priceImpactUsd = 0; 149 | | } 150 | | 151 | * | if (params.priceImpactUsd > 0) { 152 | | (int256 positiveImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 153 | | params.dataStore, 154 | | params.market.marketToken, 155 | | params.tokenOut, 156 | | params.tokenOutPrice, 157 | | params.priceImpactUsd 158 | | ); 159 | | 160 | | mintAmount += MarketUtils.usdToMarketTokenAmount( 161 | | positiveImpactAmount.toUint256() * params.tokenOutPrice.max, 162 | | poolValue, 163 | | marketTokensSupply 164 | | ); 165 | | } 166 | | 167 | * | if (params.priceImpactUsd < 0) { 168 | | (int256 negativeImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 169 | | params.dataStore, 170 | | params.market.marketToken, 171 | | params.tokenIn, 172 | | params.tokenInPrice, 173 | | params.priceImpactUsd 174 | | ); 175 | | 176 | | fees.amountAfterFees -= (-negativeImpactAmount).toUint256(); 177 | | } 178 | | 179 | * | mintAmount += MarketUtils.usdToMarketTokenAmount( 180 | * | fees.amountAfterFees * params.tokenInPrice.min, 181 | * | poolValue, 182 | * | marketTokensSupply 183 | | ); 184 | | 185 | * | return mintAmount; 186 | | } 187 | | } 188 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderPricingUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "../market/MarketStoreUtils.sol"; 10 | | 11 | | import "../deposit/DepositStoreUtils.sol"; 12 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 13 | | 14 | | import "../position/Position.sol"; 15 | | import "../position/PositionUtils.sol"; 16 | | import "../position/PositionStoreUtils.sol"; 17 | | import "../position/IncreasePositionUtils.sol"; 18 | | import "../position/DecreasePositionUtils.sol"; 19 | | 20 | | import "../order/OrderStoreUtils.sol"; 21 | | 22 | | import "../market/MarketUtils.sol"; 23 | | import "../market/Market.sol"; 24 | | 25 | | // @title ReaderPricingUtils 26 | * | library ReaderPricingUtils { 27 | | using SignedMath for int256; 28 | | using SafeCast for uint256; 29 | | using SafeCast for int256; 30 | | using Price for Price.Props; 31 | | using Position for Position.Props; 32 | | using Order for Order.Props; 33 | | 34 | | struct ExecutionPriceResult { 35 | | int256 priceImpactUsd; 36 | | uint256 priceImpactDiffUsd; 37 | | uint256 executionPrice; 38 | | } 39 | | 40 | | struct PositionInfo { 41 | | Position.Props position; 42 | | PositionPricingUtils.PositionFees fees; 43 | | ExecutionPriceResult executionPriceResult; 44 | | int256 basePnlUsd; 45 | | int256 pnlAfterPriceImpactUsd; 46 | | } 47 | | 48 | | struct GetPositionInfoCache { 49 | | Market.Props market; 50 | | Price.Props collateralTokenPrice; 51 | | uint256 pendingBorrowingFeeUsd; 52 | | int256 latestLongTokenFundingAmountPerSize; 53 | | int256 latestShortTokenFundingAmountPerSize; 54 | | } 55 | | 56 | | // returns amountOut, price impact, fees 57 | * | function getSwapAmountOut( 58 | | DataStore dataStore, 59 | | Market.Props memory market, 60 | | MarketUtils.MarketPrices memory prices, 61 | | address tokenIn, 62 | | uint256 amountIn, 63 | | address uiFeeReceiver 64 | * | ) internal view returns (uint256, int256, SwapPricingUtils.SwapFees memory) { 65 | * | SwapUtils.SwapCache memory cache; 66 | | 67 | * | if (tokenIn != market.longToken && tokenIn != market.shortToken) { 68 | | revert Errors.InvalidTokenIn(tokenIn, market.marketToken); 69 | | } 70 | | 71 | * | MarketUtils.validateSwapMarket(dataStore, market); 72 | | 73 | * | cache.tokenOut = MarketUtils.getOppositeToken(tokenIn, market); 74 | * | cache.tokenInPrice = MarketUtils.getCachedTokenPrice(tokenIn, market, prices); 75 | * | cache.tokenOutPrice = MarketUtils.getCachedTokenPrice(cache.tokenOut, market, prices); 76 | | 77 | * | int256 priceImpactUsd = SwapPricingUtils.getPriceImpactUsd( 78 | * | SwapPricingUtils.GetPriceImpactUsdParams( 79 | * | dataStore, 80 | * | market, 81 | * | tokenIn, 82 | * | cache.tokenOut, 83 | * | cache.tokenInPrice.midPrice(), 84 | * | cache.tokenOutPrice.midPrice(), 85 | * | (amountIn * cache.tokenInPrice.midPrice()).toInt256(), 86 | * | -(amountIn * cache.tokenInPrice.midPrice()).toInt256(), 87 | * | true // includeVirtualInventoryImpact 88 | | ) 89 | | ); 90 | | 91 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees( 92 | * | dataStore, 93 | * | market.marketToken, 94 | * | amountIn, 95 | * | priceImpactUsd > 0, // forPositiveImpact 96 | * | uiFeeReceiver, 97 | * | ISwapPricingUtils.SwapPricingType.TwoStep 98 | | ); 99 | | 100 | * | int256 impactAmount; 101 | | 102 | * | if (priceImpactUsd > 0) { 103 | | // when there is a positive price impact factor, additional tokens from the swap impact pool 104 | | // are withdrawn for the user 105 | | // for example, if 50,000 USDC is swapped out and there is a positive price impact 106 | | // an additional 100 USDC may be sent to the user 107 | | // the swap impact pool is decreased by the used amount 108 | | 109 | | cache.amountIn = fees.amountAfterFees; 110 | | 111 | | (impactAmount, cache.cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap( 112 | | dataStore, 113 | | market.marketToken, 114 | | cache.tokenOut, 115 | | cache.tokenOutPrice, 116 | | priceImpactUsd 117 | | ); 118 | | 119 | | if (cache.cappedDiffUsd != 0) { 120 | | (cache.tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 121 | | dataStore, 122 | | market.marketToken, 123 | | tokenIn, 124 | | cache.tokenInPrice, 125 | | cache.cappedDiffUsd.toInt256() 126 | | ); 127 | | 128 | | // this additional amountIn is already in the Market 129 | | // it is subtracted from the swap impact pool amount 130 | | // and the market pool amount is increased by the updated 131 | | // amountIn below 132 | | cache.amountIn += cache.tokenInPriceImpactAmount.toUint256(); 133 | | } 134 | | 135 | | // round amountOut down 136 | | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max; 137 | | cache.poolAmountOut = cache.amountOut; 138 | | 139 | | cache.amountOut += impactAmount.toUint256(); 140 | | } else { 141 | | // when there is a negative price impact factor, 142 | | // less of the input amount is sent to the pool 143 | | // for example, if 10 ETH is swapped in and there is a negative price impact 144 | | // only 9.995 ETH may be swapped in 145 | | // the remaining 0.005 ETH will be stored in the swap impact pool 146 | | 147 | * | (impactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 148 | * | dataStore, 149 | * | market.marketToken, 150 | * | tokenIn, 151 | * | cache.tokenInPrice, 152 | * | priceImpactUsd 153 | | ); 154 | | 155 | * | cache.amountIn = fees.amountAfterFees - (-impactAmount).toUint256(); 156 | * | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max; 157 | * | cache.poolAmountOut = cache.amountOut; 158 | | } 159 | | 160 | * | return (cache.amountOut, impactAmount, fees); 161 | | } 162 | | 163 | * | function getExecutionPrice( 164 | | DataStore dataStore, 165 | | Market.Props memory market, 166 | | Price.Props memory indexTokenPrice, 167 | | uint256 positionSizeInUsd, 168 | | uint256 positionSizeInTokens, 169 | | int256 sizeDeltaUsd, 170 | | bool isLong 171 | * | ) internal view returns (ExecutionPriceResult memory) { 172 | * | PositionUtils.UpdatePositionParams memory params; 173 | | 174 | * | params.contracts.dataStore = dataStore; 175 | * | params.market = market; 176 | | 177 | * | params.order.setSizeDeltaUsd(sizeDeltaUsd.abs()); 178 | * | params.order.setIsLong(isLong); 179 | | 180 | * | bool isIncrease = sizeDeltaUsd > 0; 181 | * | bool shouldExecutionPriceBeSmaller = isIncrease ? isLong : !isLong; 182 | * | params.order.setAcceptablePrice(shouldExecutionPriceBeSmaller ? type(uint256).max : 0); 183 | | 184 | * | params.position.setSizeInUsd(positionSizeInUsd); 185 | * | params.position.setSizeInTokens(positionSizeInTokens); 186 | * | params.position.setIsLong(isLong); 187 | | 188 | * | ExecutionPriceResult memory result; 189 | | 190 | * | if (sizeDeltaUsd > 0) { 191 | | (result.priceImpactUsd, /* priceImpactAmount */, /* sizeDeltaInTokens */, result.executionPrice) = PositionUtils.getExecutionPriceForIncrease( 192 | | params, 193 | | indexTokenPrice 194 | | ); 195 | | } else { 196 | * | (result.priceImpactUsd, result.priceImpactDiffUsd, result.executionPrice) = PositionUtils.getExecutionPriceForDecrease( 197 | * | params, 198 | * | indexTokenPrice 199 | | ); 200 | | } 201 | | 202 | * | return result; 203 | | } 204 | | 205 | | function getSwapPriceImpact( 206 | | DataStore dataStore, 207 | | Market.Props memory market, 208 | | address tokenIn, 209 | | address tokenOut, 210 | | uint256 amountIn, 211 | | Price.Props memory tokenInPrice, 212 | | Price.Props memory tokenOutPrice 213 | | ) internal view returns (int256 priceImpactUsdBeforeCap, int256 priceImpactAmount, int256 tokenInPriceImpactAmount) { 214 | | priceImpactUsdBeforeCap = SwapPricingUtils.getPriceImpactUsd( 215 | | SwapPricingUtils.GetPriceImpactUsdParams( 216 | | dataStore, 217 | | market, 218 | | tokenIn, 219 | | tokenOut, 220 | | tokenInPrice.midPrice(), 221 | | tokenOutPrice.midPrice(), 222 | | (amountIn * tokenInPrice.midPrice()).toInt256(), 223 | | -(amountIn * tokenInPrice.midPrice()).toInt256(), 224 | | true // includeVirtualInventoryImpact 225 | | ) 226 | | ); 227 | | 228 | | if (priceImpactUsdBeforeCap > 0) { 229 | | uint256 cappedDiffUsd; 230 | | (priceImpactAmount, cappedDiffUsd) = MarketUtils.getSwapImpactAmountWithCap( 231 | | dataStore, 232 | | market.marketToken, 233 | | tokenOut, 234 | | tokenOutPrice, 235 | | priceImpactUsdBeforeCap 236 | | ); 237 | | 238 | | if (cappedDiffUsd != 0) { 239 | | (tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 240 | | dataStore, 241 | | market.marketToken, 242 | | tokenIn, 243 | | tokenInPrice, 244 | | cappedDiffUsd.toInt256() 245 | | ); 246 | | } 247 | | } else { 248 | | (priceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.getSwapImpactAmountWithCap( 249 | | dataStore, 250 | | market.marketToken, 251 | | tokenIn, 252 | | tokenInPrice, 253 | | priceImpactUsdBeforeCap 254 | | ); 255 | | } 256 | | 257 | | return (priceImpactUsdBeforeCap, priceImpactAmount, tokenInPriceImpactAmount); 258 | | } 259 | | } 260 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "../market/MarketStoreUtils.sol"; 10 | | 11 | | import "../deposit/DepositStoreUtils.sol"; 12 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 13 | | 14 | | import "../position/Position.sol"; 15 | | import "../position/PositionUtils.sol"; 16 | | import "../position/PositionStoreUtils.sol"; 17 | | import "../position/IncreasePositionUtils.sol"; 18 | | import "../position/DecreasePositionUtils.sol"; 19 | | 20 | | import "../order/OrderStoreUtils.sol"; 21 | | 22 | | import "../market/MarketUtils.sol"; 23 | | import "../market/Market.sol"; 24 | | import "./ReaderPricingUtils.sol"; 25 | | 26 | | // @title ReaderUtils 27 | | // @dev Library for read utils functions 28 | | // convers some internal library functions into internal functions to reduce 29 | | // the Reader contract size 30 | * | library ReaderUtils { 31 | | using SignedMath for int256; 32 | | using SafeCast for uint256; 33 | | using SafeCast for int256; 34 | | using Price for Price.Props; 35 | | using Position for Position.Props; 36 | | using Order for Order.Props; 37 | | 38 | | struct VirtualInventory { 39 | | uint256 virtualPoolAmountForLongToken; 40 | | uint256 virtualPoolAmountForShortToken; 41 | | int256 virtualInventoryForPositions; 42 | | } 43 | | 44 | | struct MarketInfo { 45 | | Market.Props market; 46 | | uint256 borrowingFactorPerSecondForLongs; 47 | | uint256 borrowingFactorPerSecondForShorts; 48 | | BaseFundingValues baseFunding; 49 | | MarketUtils.GetNextFundingAmountPerSizeResult nextFunding; 50 | | VirtualInventory virtualInventory; 51 | | bool isDisabled; 52 | | } 53 | | 54 | | struct PositionInfo { 55 | | Position.Props position; 56 | | PositionPricingUtils.PositionFees fees; 57 | | ReaderPricingUtils.ExecutionPriceResult executionPriceResult; 58 | | int256 basePnlUsd; 59 | | int256 uncappedBasePnlUsd; 60 | | int256 pnlAfterPriceImpactUsd; 61 | | } 62 | | 63 | | struct GetPositionInfoCache { 64 | | Market.Props market; 65 | | Price.Props collateralTokenPrice; 66 | | uint256 pendingBorrowingFeeUsd; 67 | | } 68 | | 69 | | struct BaseFundingValues { 70 | | MarketUtils.PositionType fundingFeeAmountPerSize; 71 | | MarketUtils.PositionType claimableFundingAmountPerSize; 72 | | } 73 | | 74 | * | function getNextBorrowingFees( 75 | | DataStore dataStore, 76 | | Position.Props memory position, 77 | | Market.Props memory market, 78 | | MarketUtils.MarketPrices memory prices 79 | * | ) internal view returns (uint256) { 80 | * | return MarketUtils.getNextBorrowingFees( 81 | * | dataStore, 82 | * | position, 83 | * | market, 84 | * | prices 85 | | ); 86 | | } 87 | | 88 | * | function getBorrowingFees( 89 | | DataStore dataStore, 90 | | Price.Props memory collateralTokenPrice, 91 | | uint256 borrowingFeeUsd 92 | * | ) internal view returns (PositionPricingUtils.PositionBorrowingFees memory) { 93 | * | return PositionPricingUtils.getBorrowingFees( 94 | * | dataStore, 95 | * | collateralTokenPrice, 96 | * | borrowingFeeUsd 97 | | ); 98 | | } 99 | | 100 | * | function getBaseFundingValues(DataStore dataStore, Market.Props memory market) internal view returns (BaseFundingValues memory) { 101 | * | BaseFundingValues memory values; 102 | | 103 | * | values.fundingFeeAmountPerSize.long.longToken = MarketUtils.getFundingFeeAmountPerSize( 104 | * | dataStore, 105 | * | market.marketToken, 106 | * | market.longToken, 107 | * | true // isLong 108 | | ); 109 | | 110 | * | values.fundingFeeAmountPerSize.long.shortToken = MarketUtils.getFundingFeeAmountPerSize( 111 | * | dataStore, 112 | * | market.marketToken, 113 | * | market.shortToken, 114 | * | true // isLong 115 | | ); 116 | | 117 | * | values.fundingFeeAmountPerSize.short.longToken = MarketUtils.getFundingFeeAmountPerSize( 118 | * | dataStore, 119 | * | market.marketToken, 120 | * | market.longToken, 121 | * | false // isLong 122 | | ); 123 | | 124 | * | values.fundingFeeAmountPerSize.short.shortToken = MarketUtils.getFundingFeeAmountPerSize( 125 | * | dataStore, 126 | * | market.marketToken, 127 | * | market.shortToken, 128 | * | false // isLong 129 | | ); 130 | | 131 | * | values.claimableFundingAmountPerSize.long.longToken = MarketUtils.getClaimableFundingAmountPerSize( 132 | * | dataStore, 133 | * | market.marketToken, 134 | * | market.longToken, 135 | * | true // isLong 136 | | ); 137 | | 138 | * | values.claimableFundingAmountPerSize.long.shortToken = MarketUtils.getClaimableFundingAmountPerSize( 139 | * | dataStore, 140 | * | market.marketToken, 141 | * | market.shortToken, 142 | * | true // isLong 143 | | ); 144 | | 145 | * | values.claimableFundingAmountPerSize.short.longToken = MarketUtils.getClaimableFundingAmountPerSize( 146 | * | dataStore, 147 | * | market.marketToken, 148 | * | market.longToken, 149 | * | false // isLong 150 | | ); 151 | | 152 | * | values.claimableFundingAmountPerSize.short.shortToken = MarketUtils.getClaimableFundingAmountPerSize( 153 | * | dataStore, 154 | * | market.marketToken, 155 | * | market.shortToken, 156 | * | false // isLong 157 | | ); 158 | | 159 | * | return values; 160 | | } 161 | | 162 | * | function getNextFundingAmountPerSize( 163 | | DataStore dataStore, 164 | | Market.Props memory market, 165 | | MarketUtils.MarketPrices memory prices 166 | * | ) internal view returns (MarketUtils.GetNextFundingAmountPerSizeResult memory) { 167 | * | return MarketUtils.getNextFundingAmountPerSize( 168 | * | dataStore, 169 | * | market, 170 | * | prices 171 | | ); 172 | | } 173 | | 174 | * | function getMarketInfo( 175 | | DataStore dataStore, 176 | | MarketUtils.MarketPrices memory prices, 177 | | address marketKey 178 | * | ) internal view returns (MarketInfo memory) { 179 | * | Market.Props memory market = MarketStoreUtils.get(dataStore, marketKey); 180 | | 181 | * | uint256 borrowingFactorPerSecondForLongs = MarketUtils.getBorrowingFactorPerSecond( 182 | * | dataStore, 183 | * | market, 184 | * | prices, 185 | * | true 186 | | ); 187 | | 188 | * | uint256 borrowingFactorPerSecondForShorts = MarketUtils.getBorrowingFactorPerSecond( 189 | * | dataStore, 190 | * | market, 191 | * | prices, 192 | * | false 193 | | ); 194 | | 195 | * | BaseFundingValues memory baseFunding = getBaseFundingValues(dataStore, market); 196 | | 197 | * | MarketUtils.GetNextFundingAmountPerSizeResult memory nextFunding = getNextFundingAmountPerSize( 198 | * | dataStore, 199 | * | market, 200 | * | prices 201 | | ); 202 | | 203 | * | VirtualInventory memory virtualInventory = getVirtualInventory(dataStore, market); 204 | | 205 | * | bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken)); 206 | | 207 | * | return 208 | * | MarketInfo( 209 | * | market, 210 | * | borrowingFactorPerSecondForLongs, 211 | * | borrowingFactorPerSecondForShorts, 212 | * | baseFunding, 213 | * | nextFunding, 214 | * | virtualInventory, 215 | * | isMarketDisabled 216 | | ); 217 | | } 218 | | 219 | * | function getVirtualInventory( 220 | | DataStore dataStore, 221 | | Market.Props memory market 222 | * | ) internal view returns (VirtualInventory memory) { 223 | * | (, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils 224 | * | .getVirtualInventoryForSwaps(dataStore, market.marketToken); 225 | * | (, int256 virtualInventoryForPositions) = MarketUtils.getVirtualInventoryForPositions( 226 | * | dataStore, 227 | * | market.indexToken 228 | | ); 229 | | 230 | * | return 231 | * | VirtualInventory( 232 | * | virtualPoolAmountForLongToken, 233 | * | virtualPoolAmountForShortToken, 234 | * | virtualInventoryForPositions 235 | | ); 236 | | } 237 | | 238 | * | function getPositionInfo( 239 | | DataStore dataStore, 240 | | IReferralStorage referralStorage, 241 | | bytes32 positionKey, 242 | | MarketUtils.MarketPrices memory prices, 243 | | uint256 sizeDeltaUsd, 244 | | address uiFeeReceiver, 245 | | bool usePositionSizeAsSizeDeltaUsd 246 | * | ) internal view returns (PositionInfo memory) { 247 | * | PositionInfo memory positionInfo; 248 | * | GetPositionInfoCache memory cache; 249 | | 250 | * | positionInfo.position = PositionStoreUtils.get(dataStore, positionKey); 251 | * | cache.market = MarketStoreUtils.get(dataStore, positionInfo.position.market()); 252 | * | cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(positionInfo.position.collateralToken(), cache.market, prices); 253 | | 254 | * | if (usePositionSizeAsSizeDeltaUsd) { 255 | * | sizeDeltaUsd = positionInfo.position.sizeInUsd(); 256 | | } 257 | | 258 | * | positionInfo.executionPriceResult = ReaderPricingUtils.getExecutionPrice( 259 | * | dataStore, 260 | * | cache.market, 261 | * | prices.indexTokenPrice, 262 | * | positionInfo.position.sizeInUsd(), 263 | * | positionInfo.position.sizeInTokens(), 264 | * | -sizeDeltaUsd.toInt256(), 265 | * | positionInfo.position.isLong() 266 | | ); 267 | | 268 | * | PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams( 269 | * | dataStore, // dataStore 270 | * | referralStorage, // referralStorage 271 | * | positionInfo.position, // position 272 | * | cache.collateralTokenPrice, // collateralTokenPrice 273 | * | positionInfo.executionPriceResult.priceImpactUsd > 0, // forPositiveImpact 274 | * | cache.market.longToken, // longToken 275 | * | cache.market.shortToken, // shortToken 276 | * | sizeDeltaUsd, // sizeDeltaUsd 277 | * | uiFeeReceiver // uiFeeReceiver 278 | | ); 279 | | 280 | * | positionInfo.fees = PositionPricingUtils.getPositionFees(getPositionFeesParams); 281 | | 282 | | // borrowing and funding fees need to be overwritten with pending values otherwise they 283 | | // would be using storage values that have not yet been updated 284 | * | cache.pendingBorrowingFeeUsd = getNextBorrowingFees(dataStore, positionInfo.position, cache.market, prices); 285 | | 286 | * | positionInfo.fees.borrowing = getBorrowingFees( 287 | * | dataStore, 288 | * | cache.collateralTokenPrice, 289 | * | cache.pendingBorrowingFeeUsd 290 | | ); 291 | | 292 | * | MarketUtils.GetNextFundingAmountPerSizeResult memory nextFundingAmountResult = getNextFundingAmountPerSize(dataStore, cache.market, prices); 293 | | 294 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize( 295 | * | dataStore, 296 | * | positionInfo.position.market(), 297 | * | positionInfo.position.collateralToken(), 298 | * | positionInfo.position.isLong() 299 | | ); 300 | | 301 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize( 302 | * | dataStore, 303 | * | positionInfo.position.market(), 304 | * | cache.market.longToken, 305 | * | positionInfo.position.isLong() 306 | | ); 307 | | 308 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize( 309 | * | dataStore, 310 | * | positionInfo.position.market(), 311 | * | cache.market.shortToken, 312 | * | positionInfo.position.isLong() 313 | | ); 314 | | 315 | | // see MarketUtils.getNextFundingAmountPerSize for more info on why this multiplier is needed 316 | | // a short summary: 317 | | // - funding values are split based on long and short token 318 | | // - for single token markets, these tokens are the same 319 | | // - so when the funding values are applied in updateFundingState, they are applied twice 320 | | // - e.g. 321 | | // - increase fundingFeeAmountPerSize(market, collateralToken: token0, isLong: true) by 10 322 | | // - increase fundingFeeAmountPerSize(market, collateralToken: token1, isLong: true) by 10 323 | | // - for a single token market, token0 is the same as token1, so the value would be increased by 20 324 | | // - to avoid costs being doubled, these values are halved in MarketUtils.getNextFundingAmountPerSize 325 | | // - the reader code needs to double the values, because in the code below the nextFundingAmountResult 326 | | // values are applied virtually instead of the DataStore values being updated 327 | * | uint256 multiplier = cache.market.longToken == cache.market.shortToken ? 2 : 1; 328 | | 329 | * | if (positionInfo.position.isLong()) { 330 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.longToken * multiplier; 331 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.long.shortToken * multiplier; 332 | | 333 | * | if (positionInfo.position.collateralToken() == cache.market.longToken) { 334 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.longToken * multiplier; 335 | | } else { 336 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.long.shortToken * multiplier; 337 | | } 338 | | } else { 339 | * | positionInfo.fees.funding.latestLongTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.longToken * multiplier; 340 | * | positionInfo.fees.funding.latestShortTokenClaimableFundingAmountPerSize += nextFundingAmountResult.claimableFundingAmountPerSizeDelta.short.shortToken * multiplier; 341 | | 342 | * | if (positionInfo.position.collateralToken() == cache.market.longToken) { 343 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.longToken * multiplier; 344 | | } else { 345 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize += nextFundingAmountResult.fundingFeeAmountPerSizeDelta.short.shortToken * multiplier; 346 | | } 347 | | } 348 | | 349 | * | positionInfo.fees.funding = PositionPricingUtils.getFundingFees( 350 | * | positionInfo.fees.funding, 351 | * | positionInfo.position 352 | | ); 353 | | 354 | * | (positionInfo.basePnlUsd, positionInfo.uncappedBasePnlUsd, /* sizeDeltaInTokens */) = PositionUtils.getPositionPnlUsd( 355 | * | dataStore, 356 | * | cache.market, 357 | * | prices, 358 | * | positionInfo.position, 359 | * | sizeDeltaUsd 360 | | ); 361 | | 362 | * | positionInfo.pnlAfterPriceImpactUsd = positionInfo.executionPriceResult.priceImpactUsd + positionInfo.basePnlUsd; 363 | | 364 | * | positionInfo.fees.totalCostAmountExcludingFunding = 365 | * | positionInfo.fees.positionFeeAmount 366 | * | + positionInfo.fees.borrowing.borrowingFeeAmount 367 | * | + positionInfo.fees.ui.uiFeeAmount 368 | * | - positionInfo.fees.referral.traderDiscountAmount; 369 | | 370 | * | positionInfo.fees.totalCostAmount = 371 | * | positionInfo.fees.totalCostAmountExcludingFunding 372 | * | + positionInfo.fees.funding.fundingFeeAmount; 373 | | 374 | * | return positionInfo; 375 | | } 376 | | } 377 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/reader/ReaderWithdrawalUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | 7 | | import "../data/Keys.sol"; 8 | | 9 | | import "../market/MarketStoreUtils.sol"; 10 | | 11 | | import "../deposit/DepositStoreUtils.sol"; 12 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 13 | | 14 | | import "../position/Position.sol"; 15 | | import "../position/PositionUtils.sol"; 16 | | import "../position/PositionStoreUtils.sol"; 17 | | import "../position/IncreasePositionUtils.sol"; 18 | | import "../position/DecreasePositionUtils.sol"; 19 | | 20 | | import "../order/OrderStoreUtils.sol"; 21 | | 22 | | import "../market/MarketUtils.sol"; 23 | | import "../market/Market.sol"; 24 | | import "./ReaderPricingUtils.sol"; 25 | | 26 | * | library ReaderWithdrawalUtils { 27 | | using SignedMath for int256; 28 | | using SafeCast for uint256; 29 | | using SafeCast for int256; 30 | | using Price for Price.Props; 31 | | using Position for Position.Props; 32 | | using Order for Order.Props; 33 | | 34 | | struct GetWithdrawalAmountOutCache { 35 | | uint256 poolValue; 36 | | uint256 marketTokensSupply; 37 | | 38 | | uint256 longTokenPoolAmount; 39 | | uint256 shortTokenPoolAmount; 40 | | 41 | | uint256 longTokenPoolUsd; 42 | | uint256 shortTokenPoolUsd; 43 | | 44 | | uint256 totalPoolUsd; 45 | | 46 | | uint256 marketTokensUsd; 47 | | 48 | | uint256 longTokenOutputUsd; 49 | | uint256 shortTokenOutputUsd; 50 | | 51 | | uint256 longTokenOutputAmount; 52 | | uint256 shortTokenOutputAmount; 53 | | } 54 | | 55 | * | function getWithdrawalAmountOut( 56 | | DataStore dataStore, 57 | | Market.Props memory market, 58 | | MarketUtils.MarketPrices memory prices, 59 | | uint256 marketTokenAmount, 60 | | address uiFeeReceiver, 61 | | ISwapPricingUtils.SwapPricingType swapPricingType 62 | * | ) internal view returns (uint256, uint256) { 63 | * | GetWithdrawalAmountOutCache memory cache; 64 | | 65 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 66 | * | dataStore, 67 | * | market, 68 | * | prices.indexTokenPrice, 69 | * | prices.longTokenPrice, 70 | * | prices.shortTokenPrice, 71 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, 72 | * | false 73 | | ); 74 | | 75 | * | if (poolValueInfo.poolValue <= 0) { 76 | | revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue); 77 | | } 78 | | 79 | * | cache.poolValue = poolValueInfo.poolValue.toUint256(); 80 | * | cache.marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken))); 81 | | 82 | * | cache.longTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.longToken); 83 | * | cache.shortTokenPoolAmount = MarketUtils.getPoolAmount(dataStore, market, market.shortToken); 84 | | 85 | * | cache.longTokenPoolUsd = cache.longTokenPoolAmount * prices.longTokenPrice.max; 86 | * | cache.shortTokenPoolUsd = cache.shortTokenPoolAmount * prices.shortTokenPrice.max; 87 | | 88 | * | cache.totalPoolUsd = cache.longTokenPoolUsd + cache.shortTokenPoolUsd; 89 | | 90 | * | cache.marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, cache.poolValue, cache.marketTokensSupply); 91 | | 92 | * | cache.longTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.longTokenPoolUsd, cache.totalPoolUsd); 93 | * | cache.shortTokenOutputUsd = Precision.mulDiv(cache.marketTokensUsd, cache.shortTokenPoolUsd, cache.totalPoolUsd); 94 | | 95 | * | cache.longTokenOutputAmount = cache.longTokenOutputUsd / prices.longTokenPrice.max; 96 | * | cache.shortTokenOutputAmount = cache.shortTokenOutputUsd / prices.shortTokenPrice.max; 97 | | 98 | * | SwapPricingUtils.SwapFees memory longTokenFees = SwapPricingUtils.getSwapFees( 99 | * | dataStore, 100 | * | market.marketToken, 101 | * | cache.longTokenOutputAmount, 102 | * | false, // forPositiveImpact 103 | * | uiFeeReceiver, 104 | * | swapPricingType 105 | | ); 106 | | 107 | * | SwapPricingUtils.SwapFees memory shortTokenFees = SwapPricingUtils.getSwapFees( 108 | * | dataStore, 109 | * | market.marketToken, 110 | * | cache.shortTokenOutputAmount, 111 | * | false, // forPositiveImpact 112 | * | uiFeeReceiver, 113 | * | swapPricingType 114 | | ); 115 | | 116 | * | return ( 117 | * | longTokenFees.amountAfterFees, 118 | * | shortTokenFees.amountAfterFees 119 | | ); 120 | | } 121 | | } 122 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/IReferralStorage.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./ReferralTier.sol"; 6 | | 7 | | // @title IReferralStorage 8 | | // @dev Interface for ReferralStorage 9 | | interface IReferralStorage { 10 | | // @dev get the owner of a referral code 11 | | // @param _code the referral code 12 | | // @return the owner of the referral code 13 | | function codeOwners(bytes32 _code) external view returns (address); 14 | | // @dev get the referral code of a trader 15 | | // @param _account the address of the trader 16 | | // @return the referral code 17 | | function traderReferralCodes(address _account) external view returns (bytes32); 18 | | // @dev get the trader discount share for an affiliate 19 | | // @param _account the address of the affiliate 20 | | // @return the trader discount share 21 | | function referrerDiscountShares(address _account) external view returns (uint256); 22 | | // @dev get the tier level of an affiliate 23 | | // @param _account the address of the affiliate 24 | | // @return the tier level of the affiliate 25 | | function referrerTiers(address _account) external view returns (uint256); 26 | | // @dev get the referral info for a trader 27 | | // @param _account the address of the trader 28 | | // @return (referral code, affiliate) 29 | | function getTraderReferralInfo(address _account) external view returns (bytes32, address); 30 | | // @dev set the referral code for a trader 31 | | // @param _account the address of the trader 32 | | // @param _code the referral code 33 | | function setTraderReferralCode(address _account, bytes32 _code) external; 34 | | // @dev set the values for a tier 35 | | // @param _tierId the tier level 36 | | // @param _totalRebate the total rebate for the tier (affiliate reward + trader discount) 37 | | // @param _discountShare the share of the totalRebate for traders 38 | | function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external; 39 | | // @dev set the tier for an affiliate 40 | | // @param _tierId the tier level 41 | | function setReferrerTier(address _referrer, uint256 _tierId) external; 42 | | // @dev set the owner for a referral code 43 | | // @param _code the referral code 44 | | // @param _newAccount the new owner 45 | | function govSetCodeOwner(bytes32 _code, address _newAccount) external; 46 | | 47 | | // @dev get the tier values for a tier level 48 | | // @param _tierLevel the tier level 49 | | // @return (totalRebate, discountShare) 50 | | function tiers(uint256 _tierLevel) external view returns (uint256, uint256); 51 | | } 52 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | * | library ReferralEventUtils { 10 | | using EventUtils for EventUtils.AddressItems; 11 | | using EventUtils for EventUtils.UintItems; 12 | | using EventUtils for EventUtils.IntItems; 13 | | using EventUtils for EventUtils.BoolItems; 14 | | using EventUtils for EventUtils.Bytes32Items; 15 | | using EventUtils for EventUtils.BytesItems; 16 | | using EventUtils for EventUtils.StringItems; 17 | | 18 | | function emitAffiliateRewardUpdated( 19 | | EventEmitter eventEmitter, 20 | | address market, 21 | | address token, 22 | | address affiliate, 23 | | uint256 delta, 24 | | uint256 nextValue, 25 | | uint256 nextPoolValue 26 | | ) internal { 27 | | EventUtils.EventLogData memory eventData; 28 | | 29 | | eventData.addressItems.initItems(3); 30 | | eventData.addressItems.setItem(0, "market", market); 31 | | eventData.addressItems.setItem(1, "token", token); 32 | | eventData.addressItems.setItem(2, "affiliate", affiliate); 33 | | 34 | | eventData.uintItems.initItems(3); 35 | | eventData.uintItems.setItem(0, "delta", delta); 36 | | eventData.uintItems.setItem(1, "nextValue", nextValue); 37 | | eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue); 38 | | 39 | | eventEmitter.emitEventLog2( 40 | | "AffiliateRewardUpdated", 41 | | Cast.toBytes32(market), 42 | | Cast.toBytes32(affiliate), 43 | | eventData 44 | | ); 45 | | } 46 | | 47 | | function emitAffiliateRewardClaimed( 48 | | EventEmitter eventEmitter, 49 | | address market, 50 | | address token, 51 | | address affiliate, 52 | | address receiver, 53 | | uint256 amount, 54 | | uint256 nextPoolValue 55 | | ) internal { 56 | | EventUtils.EventLogData memory eventData; 57 | | 58 | | eventData.addressItems.initItems(4); 59 | | eventData.addressItems.setItem(0, "market", market); 60 | | eventData.addressItems.setItem(1, "token", token); 61 | | eventData.addressItems.setItem(2, "affiliate", affiliate); 62 | | eventData.addressItems.setItem(3, "receiver", receiver); 63 | | 64 | | eventData.uintItems.initItems(2); 65 | | eventData.uintItems.setItem(0, "amount", amount); 66 | | eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue); 67 | | 68 | | eventEmitter.emitEventLog1( 69 | | "AffiliateRewardClaimed", 70 | | Cast.toBytes32(affiliate), 71 | | eventData 72 | | ); 73 | | } 74 | | } 75 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralTier.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // @title ReferralTier 6 | | // @dev Struct for referral tiers 7 | * | library ReferralTier { 8 | | // @param totalRebate the total rebate for the tier (affiliate reward + trader discount) 9 | | // @param discountShare the share of the totalRebate for traders 10 | | struct Props { 11 | | uint256 totalRebate; 12 | | uint256 discountShare; 13 | | } 14 | | } 15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/referral/ReferralUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../data/Keys.sol"; 7 | | 8 | | import "../event/EventEmitter.sol"; 9 | | import "../market/MarketToken.sol"; 10 | | import "../market/MarketUtils.sol"; 11 | | 12 | | import "./IReferralStorage.sol"; 13 | | import "./ReferralTier.sol"; 14 | | import "./ReferralEventUtils.sol"; 15 | | 16 | | import "../utils/Precision.sol"; 17 | | 18 | | // @title ReferralUtils 19 | | // @dev Library for referral functions 20 | * | library ReferralUtils { 21 | | // @dev set the referral code for a trader 22 | | // @param referralStorage The referral storage instance to use. 23 | | // @param account The account of the trader. 24 | | // @param referralCode The referral code. 25 | * | function setTraderReferralCode( 26 | | IReferralStorage referralStorage, 27 | | address account, 28 | | bytes32 referralCode 29 | | ) internal { 30 | * | if (referralCode == bytes32(0)) { return; } 31 | | 32 | | // skip setting of the referral code if the user already has a referral code 33 | | if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; } 34 | | 35 | | referralStorage.setTraderReferralCode(account, referralCode); 36 | | } 37 | | 38 | | // @dev Increments the affiliate's reward balance by the specified delta. 39 | | // @param dataStore The data store instance to use. 40 | | // @param eventEmitter The event emitter instance to use. 41 | | // @param market The market address. 42 | | // @param token The token address. 43 | | // @param affiliate The affiliate's address. 44 | | // @param trader The trader's address. 45 | | // @param delta The amount to increment the reward balance by. 46 | * | function incrementAffiliateReward( 47 | | DataStore dataStore, 48 | | EventEmitter eventEmitter, 49 | | address market, 50 | | address token, 51 | | address affiliate, 52 | | uint256 delta 53 | | ) internal { 54 | * | if (delta == 0) { return; } 55 | | 56 | | uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta); 57 | | uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta); 58 | | 59 | | ReferralEventUtils.emitAffiliateRewardUpdated( 60 | | eventEmitter, 61 | | market, 62 | | token, 63 | | affiliate, 64 | | delta, 65 | | nextValue, 66 | | nextPoolValue 67 | | ); 68 | | } 69 | | 70 | | // @dev Gets the referral information for the specified trader. 71 | | // @param referralStorage The referral storage instance to use. 72 | | // @param trader The trader's address. 73 | | // @return The affiliate's address, the total rebate, and the discount share. 74 | * | function getReferralInfo( 75 | | IReferralStorage referralStorage, 76 | | address trader 77 | * | ) internal view returns (bytes32, address, uint256, uint256) { 78 | * | bytes32 code = referralStorage.traderReferralCodes(trader); 79 | * | address affiliate; 80 | * | uint256 totalRebate; 81 | * | uint256 discountShare; 82 | | 83 | * | if (code != bytes32(0)) { 84 | | affiliate = referralStorage.codeOwners(code); 85 | | uint256 referralTierLevel = referralStorage.referrerTiers(affiliate); 86 | | (totalRebate, discountShare) = referralStorage.tiers(referralTierLevel); 87 | | 88 | | uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate); 89 | | if (customDiscountShare != 0) { 90 | | discountShare = customDiscountShare; 91 | | } 92 | | } 93 | | 94 | * | return ( 95 | * | code, 96 | * | affiliate, 97 | * | Precision.basisPointsToFloat(totalRebate), 98 | * | Precision.basisPointsToFloat(discountShare) 99 | | ); 100 | | } 101 | | 102 | | // @dev Claims the affiliate's reward balance and transfers it to the specified receiver. 103 | | // @param dataStore The data store instance to use. 104 | | // @param eventEmitter The event emitter instance to use. 105 | | // @param market The market address. 106 | | // @param token The token address. 107 | | // @param account The affiliate's address. 108 | | // @param receiver The address to receive the reward. 109 | | function claimAffiliateReward( 110 | | DataStore dataStore, 111 | | EventEmitter eventEmitter, 112 | | address market, 113 | | address token, 114 | | address account, 115 | | address receiver 116 | | ) internal returns (uint256) { 117 | | bytes32 key = Keys.affiliateRewardKey(market, token, account); 118 | | 119 | | uint256 rewardAmount = dataStore.getUint(key); 120 | | dataStore.setUint(key, 0); 121 | | 122 | | uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount); 123 | | 124 | | MarketToken(payable(market)).transferOut( 125 | | token, 126 | | receiver, 127 | | rewardAmount 128 | | ); 129 | | 130 | | MarketUtils.validateMarketTokenBalance(dataStore, market); 131 | | 132 | | ReferralEventUtils.emitAffiliateRewardClaimed( 133 | | eventEmitter, 134 | | market, 135 | | token, 136 | | account, 137 | | receiver, 138 | | rewardAmount, 139 | | nextPoolValue 140 | | ); 141 | | 142 | | return rewardAmount; 143 | | } 144 | | } 145 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/Role.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @title Role 7 | | * @dev Library for role keys 8 | | */ 9 | * | library Role { 10 | | /** 11 | | * @dev The ROLE_ADMIN role. 12 | | * Hash: 0x56908b85b56869d7c69cd020749874f238259af9646ca930287866cdd660b7d9 13 | | */ 14 | | bytes32 internal constant ROLE_ADMIN = keccak256(abi.encode("ROLE_ADMIN")); 15 | | 16 | | /** 17 | | * @dev The TIMELOCK_ADMIN role. 18 | | * Hash: 0xf49b0c86b385620e25b0985905d1a112a5f1bc1d51a7a292a8cdf112b3a7c47c 19 | | */ 20 | | bytes32 internal constant TIMELOCK_ADMIN = keccak256(abi.encode("TIMELOCK_ADMIN")); 21 | | 22 | | /** 23 | | * @dev The TIMELOCK_MULTISIG role. 24 | | * Hash: 0xe068a8d811c3c8290a8be34607cfa3184b26ffb8dea4dde7a451adfba9fa173a 25 | | */ 26 | | bytes32 internal constant TIMELOCK_MULTISIG = keccak256(abi.encode("TIMELOCK_MULTISIG")); 27 | | 28 | | /** 29 | | * @dev The CONFIG_KEEPER role. 30 | | * Hash: 0x901fb3de937a1dcb6ecaf26886fda47a088e74f36232a0673eade97079dc225b 31 | | */ 32 | | bytes32 internal constant CONFIG_KEEPER = keccak256(abi.encode("CONFIG_KEEPER")); 33 | | 34 | | /** 35 | | * @dev The LIMITED_CONFIG_KEEPER role. 36 | | * Hash: 0xb49beded4d572a2d32002662fc5c735817329f4337b3a488aab0b5e835c01ba7 37 | | */ 38 | | bytes32 internal constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode("LIMITED_CONFIG_KEEPER")); 39 | | 40 | | /** 41 | | * @dev The CONTROLLER role. 42 | | * Hash: 0x97adf037b2472f4a6a9825eff7d2dd45e37f2dc308df2a260d6a72af4189a65b 43 | | */ 44 | * | bytes32 internal constant CONTROLLER = keccak256(abi.encode("CONTROLLER")); 45 | | 46 | | /** 47 | | * @dev The GOV_TOKEN_CONTROLLER role. 48 | | * Hash: 0x16a157db08319d4eaf6b157a71f5d2e18c6500cab8a25bee0b4f9c753cb13690 49 | | */ 50 | | bytes32 internal constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode("GOV_TOKEN_CONTROLLER")); 51 | | 52 | | /** 53 | | * @dev The ROUTER_PLUGIN role. 54 | | * Hash: 0xc82e6cc76072f8edb32d42796e58e13ab6e145524eb6b36c073be82f20d410f3 55 | | */ 56 | * | bytes32 internal constant ROUTER_PLUGIN = keccak256(abi.encode("ROUTER_PLUGIN")); 57 | | 58 | | /** 59 | | * @dev The MARKET_KEEPER role. 60 | | * Hash: 0xd66692c70b60cf1337e643d6a6473f6865d8c03f3c26b460df3d19b504fb46ae 61 | | */ 62 | | bytes32 internal constant MARKET_KEEPER = keccak256(abi.encode("MARKET_KEEPER")); 63 | | 64 | | /** 65 | | * @dev The FEE_KEEPER role. 66 | | * Hash: 0xe0ff4cc0c6ecffab6db3f63ea62dd53f8091919ac57669f1bb3d9828278081d8 67 | | */ 68 | | bytes32 internal constant FEE_KEEPER = keccak256(abi.encode("FEE_KEEPER")); 69 | | 70 | | /** 71 | | * @dev The FEE_DISTRIBUTION_KEEPER role. 72 | | * Hash: 0xc23a98a1bf683201c11eeeb8344052ad3bc603c8ddcad06093edc1e8dafa96a2 73 | | */ 74 | | bytes32 internal constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode("FEE_DISTRIBUTION_KEEPER")); 75 | | 76 | | /** 77 | | * @dev The ORDER_KEEPER role. 78 | | * Hash: 0x40a07f8f0fc57fcf18b093d96362a8e661eaac7b7e6edbf66f242111f83a6794 79 | | */ 80 | * | bytes32 internal constant ORDER_KEEPER = keccak256(abi.encode("ORDER_KEEPER")); 81 | | 82 | | /** 83 | | * @dev The FROZEN_ORDER_KEEPER role. 84 | | * Hash: 0xcb6c7bc0d25d73c91008af44527b80c56dee4db8965845d926a25659a4a8bc07 85 | | */ 86 | * | bytes32 internal constant FROZEN_ORDER_KEEPER = keccak256(abi.encode("FROZEN_ORDER_KEEPER")); 87 | | 88 | | /** 89 | | * @dev The PRICING_KEEPER role. 90 | | * Hash: 0x2700e36dc4e6a0daa977bffd4368adbd48f8058da74152919f91f58eddb42103 91 | | */ 92 | | bytes32 internal constant PRICING_KEEPER = keccak256(abi.encode("PRICING_KEEPER")); 93 | | /** 94 | | * @dev The LIQUIDATION_KEEPER role. 95 | | * Hash: 0x556c788ffc0574ec93966d808c170833d96489c9c58f5bcb3dadf711ba28720e 96 | | */ 97 | * | bytes32 internal constant LIQUIDATION_KEEPER = keccak256(abi.encode("LIQUIDATION_KEEPER")); 98 | | /** 99 | | * @dev The ADL_KEEPER role. 100 | | * Hash: 0xb37d64edaeaf5e634c13682dbd813f5a12fec9eb4f74433a089e7a3c3289af91 101 | | */ 102 | * | bytes32 internal constant ADL_KEEPER = keccak256(abi.encode("ADL_KEEPER")); 103 | | } 104 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/RoleModule.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./RoleStore.sol"; 6 | | 7 | | /** 8 | | * @title RoleModule 9 | | * @dev Contract for role validation functions 10 | | */ 11 | | contract RoleModule { 12 | | RoleStore public immutable roleStore; 13 | | 14 | | /** 15 | | * @dev Constructor that initializes the role store for this contract. 16 | | * 17 | | * @param _roleStore The contract instance to use as the role store. 18 | | */ 19 | | constructor(RoleStore _roleStore) { 20 | | roleStore = _roleStore; 21 | | } 22 | | 23 | | /** 24 | | * @dev Only allows the contract's own address to call the function. 25 | | */ 26 | | modifier onlySelf() { 27 | * | if (msg.sender != address(this)) { 28 | | revert Errors.Unauthorized(msg.sender, "SELF"); 29 | | } 30 | | _; 31 | | } 32 | | 33 | | /** 34 | | * @dev Only allows addresses with the TIMELOCK_MULTISIG role to call the function. 35 | | */ 36 | | modifier onlyTimelockMultisig() { 37 | | _validateRole(Role.TIMELOCK_MULTISIG, "TIMELOCK_MULTISIG"); 38 | | _; 39 | | } 40 | | 41 | | /** 42 | | * @dev Only allows addresses with the TIMELOCK_ADMIN role to call the function. 43 | | */ 44 | | modifier onlyTimelockAdmin() { 45 | | _validateRole(Role.TIMELOCK_ADMIN, "TIMELOCK_ADMIN"); 46 | | _; 47 | | } 48 | | 49 | | /** 50 | | * @dev Only allows addresses with the CONFIG_KEEPER role to call the function. 51 | | */ 52 | | modifier onlyConfigKeeper() { 53 | | _validateRole(Role.CONFIG_KEEPER, "CONFIG_KEEPER"); 54 | | _; 55 | | } 56 | | 57 | | /** 58 | | * @dev Only allows addresses with the CONTROLLER role to call the function. 59 | | */ 60 | | modifier onlyController() { 61 | * | _validateRole(Role.CONTROLLER, "CONTROLLER"); 62 | * | _; 63 | | } 64 | | 65 | | /** 66 | | * @dev Only allows addresses with the GOV_TOKEN_CONTROLLER role to call the function. 67 | | */ 68 | | modifier onlyGovTokenController() { 69 | | _validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER"); 70 | | _; 71 | | } 72 | | 73 | | /** 74 | | * @dev Only allows addresses with the ROUTER_PLUGIN role to call the function. 75 | | */ 76 | | modifier onlyRouterPlugin() { 77 | * | _validateRole(Role.ROUTER_PLUGIN, "ROUTER_PLUGIN"); 78 | | _; 79 | | } 80 | | 81 | | /** 82 | | * @dev Only allows addresses with the MARKET_KEEPER role to call the function. 83 | | */ 84 | | modifier onlyMarketKeeper() { 85 | | _validateRole(Role.MARKET_KEEPER, "MARKET_KEEPER"); 86 | | _; 87 | | } 88 | | 89 | | /** 90 | | * @dev Only allows addresses with the FEE_KEEPER role to call the function. 91 | | */ 92 | | modifier onlyFeeKeeper() { 93 | | _validateRole(Role.FEE_KEEPER, "FEE_KEEPER"); 94 | | _; 95 | | } 96 | | 97 | | /** 98 | | * @dev Only allows addresses with the FEE_DISTRIBUTION_KEEPER role to call the function. 99 | | */ 100 | | modifier onlyFeeDistributionKeeper() { 101 | | _validateRole(Role.FEE_DISTRIBUTION_KEEPER, "FEE_DISTRIBUTION_KEEPER"); 102 | | _; 103 | | } 104 | | 105 | | /** 106 | | * @dev Only allows addresses with the ORDER_KEEPER role to call the function. 107 | | */ 108 | | modifier onlyOrderKeeper() { 109 | * | _validateRole(Role.ORDER_KEEPER, "ORDER_KEEPER"); 110 | * | _; 111 | | } 112 | | 113 | | /** 114 | | * @dev Only allows addresses with the PRICING_KEEPER role to call the function. 115 | | */ 116 | | modifier onlyPricingKeeper() { 117 | | _validateRole(Role.PRICING_KEEPER, "PRICING_KEEPER"); 118 | | _; 119 | | } 120 | | 121 | | /** 122 | | * @dev Only allows addresses with the LIQUIDATION_KEEPER role to call the function. 123 | | */ 124 | | modifier onlyLiquidationKeeper() { 125 | * | _validateRole(Role.LIQUIDATION_KEEPER, "LIQUIDATION_KEEPER"); 126 | * | _; 127 | | } 128 | | 129 | | /** 130 | | * @dev Only allows addresses with the ADL_KEEPER role to call the function. 131 | | */ 132 | | modifier onlyAdlKeeper() { 133 | * | _validateRole(Role.ADL_KEEPER, "ADL_KEEPER"); 134 | * | _; 135 | | } 136 | | 137 | | /** 138 | | * @dev Validates that the caller has the specified role. 139 | | * 140 | | * If the caller does not have the specified role, the transaction is reverted. 141 | | * 142 | | * @param role The key of the role to validate. 143 | | * @param roleName The name of the role to validate. 144 | | */ 145 | * | function _validateRole(bytes32 role, string memory roleName) internal view { 146 | * | if (!roleStore.hasRole(msg.sender, role)) { 147 | | revert Errors.Unauthorized(msg.sender, roleName); 148 | | } 149 | | } 150 | | } 151 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/role/RoleStore.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 6 | | import "../utils/EnumerableValues.sol"; 7 | | import "./Role.sol"; 8 | | import "../error/Errors.sol"; 9 | | 10 | | /** 11 | | * @title RoleStore 12 | | * @dev Stores roles and their members. 13 | | */ 14 | * | contract RoleStore { 15 | | using EnumerableSet for EnumerableSet.AddressSet; 16 | | using EnumerableSet for EnumerableSet.Bytes32Set; 17 | | using EnumerableValues for EnumerableSet.AddressSet; 18 | | using EnumerableValues for EnumerableSet.Bytes32Set; 19 | | 20 | | EnumerableSet.Bytes32Set internal roles; 21 | | mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers; 22 | | // checking if an account has a role is a frequently used function 23 | | // roleCache helps to save gas by offering a more efficient lookup 24 | | // vs calling roleMembers[key].contains(account) 25 | | mapping(address => mapping (bytes32 => bool)) roleCache; 26 | | 27 | | modifier onlyRoleAdmin() { 28 | | if (!hasRole(msg.sender, Role.ROLE_ADMIN)) { 29 | | revert Errors.Unauthorized(msg.sender, "ROLE_ADMIN"); 30 | | } 31 | | _; 32 | | } 33 | | 34 | | constructor() { 35 | | _grantRole(msg.sender, Role.ROLE_ADMIN); 36 | | } 37 | | 38 | | /** 39 | | * @dev Grants the specified role to the given account. 40 | | * 41 | | * @param account The address of the account. 42 | | * @param roleKey The key of the role to grant. 43 | | */ 44 | | function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin { 45 | | _grantRole(account, roleKey); 46 | | } 47 | | 48 | | /** 49 | | * @dev Revokes the specified role from the given account. 50 | | * 51 | | * @param account The address of the account. 52 | | * @param roleKey The key of the role to revoke. 53 | | */ 54 | | function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin { 55 | | _revokeRole(account, roleKey); 56 | | } 57 | | 58 | | /** 59 | | * @dev Returns true if the given account has the specified role. 60 | | * 61 | | * @param account The address of the account. 62 | | * @param roleKey The key of the role. 63 | | * @return True if the account has the role, false otherwise. 64 | | */ 65 | * | function hasRole(address account, bytes32 roleKey) public view returns (bool) { 66 | * | return roleCache[account][roleKey]; 67 | | } 68 | | 69 | | /** 70 | | * @dev Returns the number of roles stored in the contract. 71 | | * 72 | | * @return The number of roles. 73 | | */ 74 | | function getRoleCount() external view returns (uint256) { 75 | | return roles.length(); 76 | | } 77 | | 78 | | /** 79 | | * @dev Returns the keys of the roles stored in the contract. 80 | | * 81 | | * @param start The starting index of the range of roles to return. 82 | | * @param end The ending index of the range of roles to return. 83 | | * @return The keys of the roles. 84 | | */ 85 | | function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) { 86 | | return roles.valuesAt(start, end); 87 | | } 88 | | 89 | | /** 90 | | * @dev Returns the number of members of the specified role. 91 | | * 92 | | * @param roleKey The key of the role. 93 | | * @return The number of members of the role. 94 | | */ 95 | | function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) { 96 | | return roleMembers[roleKey].length(); 97 | | } 98 | | 99 | | /** 100 | | * @dev Returns the members of the specified role. 101 | | * 102 | | * @param roleKey The key of the role. 103 | | * @param start the start index, the value for this index will be included. 104 | | * @param end the end index, the value for this index will not be included. 105 | | * @return The members of the role. 106 | | */ 107 | | function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) { 108 | | return roleMembers[roleKey].valuesAt(start, end); 109 | | } 110 | | 111 | | function _grantRole(address account, bytes32 roleKey) internal { 112 | | roles.add(roleKey); 113 | | roleMembers[roleKey].add(account); 114 | | roleCache[account][roleKey] = true; 115 | | } 116 | | 117 | | function _revokeRole(address account, bytes32 roleKey) internal { 118 | | roleMembers[roleKey].remove(account); 119 | | roleCache[account][roleKey] = false; 120 | | 121 | | if (roleMembers[roleKey].length() == 0) { 122 | | if (roleKey == Role.ROLE_ADMIN) { 123 | | revert Errors.ThereMustBeAtLeastOneRoleAdmin(); 124 | | } 125 | | if (roleKey == Role.TIMELOCK_MULTISIG) { 126 | | revert Errors.ThereMustBeAtLeastOneTimelockMultiSig(); 127 | | } 128 | | } 129 | | } 130 | | } 131 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/BaseRouter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 8 | | 9 | | import "../utils/PayableMulticall.sol"; 10 | | import "../utils/AccountUtils.sol"; 11 | | 12 | | import "../data/DataStore.sol"; 13 | | import "../event/EventEmitter.sol"; 14 | | import "../token/TokenUtils.sol"; 15 | | 16 | | import "./Router.sol"; 17 | | 18 | | contract BaseRouter is ReentrancyGuard, PayableMulticall, RoleModule { 19 | | using SafeERC20 for IERC20; 20 | | event BaseRouterDeployed(address deployedTo); 21 | | 22 | | Router public immutable router; 23 | | DataStore public immutable dataStore; 24 | | EventEmitter public immutable eventEmitter; 25 | | 26 | | constructor( 27 | | Router _router, 28 | | RoleStore _roleStore, 29 | | DataStore _dataStore, 30 | | EventEmitter _eventEmitter 31 | | ) RoleModule(_roleStore) { 32 | | router = _router; 33 | | dataStore = _dataStore; 34 | | eventEmitter = _eventEmitter; 35 | | 36 | | emit BaseRouterDeployed(address(this)); 37 | | } 38 | | 39 | | // @dev Wraps the specified amount of native tokens into WNT then sends the WNT to the specified address 40 | * | function sendWnt( 41 | | address receiver, 42 | | uint256 amount 43 | | ) external payable nonReentrant { 44 | * | AccountUtils.validateReceiver(receiver); 45 | * | TokenUtils.depositAndSendWrappedNativeToken( 46 | * | dataStore, 47 | * | receiver, 48 | * | amount 49 | | ); 50 | | } 51 | | 52 | | // @dev Sends the given amount of tokens to the given address 53 | * | function sendTokens( 54 | | address token, 55 | | address receiver, 56 | | uint256 amount 57 | * | ) external payable nonReentrant { 58 | * | AccountUtils.validateReceiver(receiver); 59 | * | address account = msg.sender; 60 | * | router.pluginTransfer(token, account, receiver, amount); 61 | | } 62 | | 63 | | function sendNativeToken( 64 | | address receiver, 65 | | uint256 amount 66 | | ) external payable nonReentrant { 67 | | AccountUtils.validateReceiver(receiver); 68 | | TokenUtils.sendNativeToken(dataStore, receiver, amount); 69 | | } 70 | | } 71 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/ExchangeRouter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../exchange/IDepositHandler.sol"; 6 | | import "../exchange/IWithdrawalHandler.sol"; 7 | | import "../exchange/IShiftHandler.sol"; 8 | | import "../exchange/IOrderHandler.sol"; 9 | | import "../external/IExternalHandler.sol"; 10 | | 11 | | import "../feature/FeatureUtils.sol"; 12 | | 13 | | import "./BaseRouter.sol"; 14 | | import "./IExchangeRouter.sol"; 15 | | 16 | | /** 17 | | * @title ExchangeRouter 18 | | * @dev Router for exchange functions, supports functions which require 19 | | * token transfers from the user 20 | | * 21 | | * IMPORTANT: PayableMulticall uses delegatecall, msg.value will be the same for each delegatecall 22 | | * extra care should be taken when using msg.value in any of the functions in this contract 23 | | * 24 | | * To avoid front-running issues, most actions require two steps to execute: 25 | | * 26 | | * - User sends transaction with request details, e.g. deposit / withdraw liquidity, 27 | | * swap, increase / decrease position 28 | | * - Keepers listen for the transactions, include the prices for the request then 29 | | * send a transaction to execute the request 30 | | * 31 | | * Prices are provided by an off-chain oracle system: 32 | | * 33 | | * - Oracle keepers continually check the latest blocks 34 | | * - When there is a new block, oracle keepers fetch the latest prices from 35 | | * reference exchanges 36 | | * - Oracle keepers then sign the median price for each token together with 37 | | * the block hash 38 | | * - Oracle keepers then send the data and signature to archive nodes 39 | | * - Archive nodes display this information for anyone to query 40 | | * 41 | | * Example: 42 | | * 43 | | * - Block 100 is finalized on the blockchain 44 | | * - Oracle keepers observe this block 45 | | * - Oracle keepers pull the latest prices from reference exchanges, 46 | | * token A: price 20,000, token B: price 80,000 47 | | * - Oracle keepers sign [chainId, blockhash(100), 20,000], [chainId, blockhash(100), 80,000] 48 | | * - If in block 100, there was a market order to open a long position for token A, 49 | | * the market order would have a block number of 100 50 | | * - The prices signed at block 100 can be used to execute this order 51 | | * - Order keepers would bundle the signature and price data for token A 52 | | * then execute the order 53 | | */ 54 | * | contract ExchangeRouter is IExchangeRouter, BaseRouter { 55 | | using Deposit for Deposit.Props; 56 | | using Withdrawal for Withdrawal.Props; 57 | | using Order for Order.Props; 58 | | using Shift for Shift.Props; 59 | | 60 | | IDepositHandler public immutable depositHandler; 61 | | IWithdrawalHandler public immutable withdrawalHandler; 62 | | IShiftHandler public immutable shiftHandler; 63 | | IOrderHandler public immutable orderHandler; 64 | | IExternalHandler public immutable externalHandler; 65 | | 66 | | // @dev Constructor that initializes the contract with the provided Router, RoleStore, DataStore, 67 | | // EventEmitter, IDepositHandler, IWithdrawalHandler, IOrderHandler, and OrderStore instances 68 | | constructor( 69 | | Router _router, 70 | | RoleStore _roleStore, 71 | | DataStore _dataStore, 72 | | EventEmitter _eventEmitter, 73 | | IDepositHandler _depositHandler, 74 | | IWithdrawalHandler _withdrawalHandler, 75 | | IShiftHandler _shiftHandler, 76 | | IOrderHandler _orderHandler, 77 | | IExternalHandler _externalHandler 78 | | ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) { 79 | | depositHandler = _depositHandler; 80 | | withdrawalHandler = _withdrawalHandler; 81 | | shiftHandler = _shiftHandler; 82 | | orderHandler = _orderHandler; 83 | | externalHandler = _externalHandler; 84 | | } 85 | | 86 | | // makeExternalCalls can be used to perform an external swap before 87 | | // an action 88 | | // example: 89 | | // - ExchangeRouter.sendTokens(token: WETH, receiver: externalHandler, amount: 1e18) 90 | | // - ExchangeRouter.makeExternalCalls( 91 | | // WETH.approve(spender: aggregator, amount: 1e18), 92 | | // aggregator.swap(amount: 1, from: WETH, to: USDC, receiver: orderHandler) 93 | | // ) 94 | | // - ExchangeRouter.createOrder 95 | | // the msg.sender for makeExternalCalls would be externalHandler 96 | | // refundTokens can be used to retrieve any excess tokens that may 97 | | // be left in the externalHandler 98 | | function makeExternalCalls( 99 | | address[] memory externalCallTargets, 100 | | bytes[] memory externalCallDataList, 101 | | address[] memory refundTokens, 102 | | address[] memory refundReceivers 103 | | ) external { 104 | | externalHandler.makeExternalCalls( 105 | | externalCallTargets, 106 | | externalCallDataList, 107 | | refundTokens, 108 | | refundReceivers 109 | | ); 110 | | } 111 | | 112 | | /** 113 | | * @dev Creates a new deposit with the given long token, short token, long token amount, short token 114 | | * amount, and deposit parameters. The deposit is created by transferring the specified amounts of 115 | | * long and short tokens from the caller's account to the deposit store, and then calling the 116 | | * `createDeposit()` function on the deposit handler contract. 117 | | * 118 | | * @param params The deposit parameters, as specified in the `DepositUtils.CreateDepositParams` struct 119 | | * @return The unique ID of the newly created deposit 120 | | */ 121 | * | function createDeposit( 122 | | DepositUtils.CreateDepositParams calldata params 123 | * | ) external payable override nonReentrant returns (bytes32) { 124 | * | address account = msg.sender; 125 | | 126 | * | return depositHandler.createDeposit(account, params); 127 | | } 128 | | 129 | * | function cancelDeposit(bytes32 key) external payable override nonReentrant { 130 | * | Deposit.Props memory deposit = DepositStoreUtils.get(dataStore, key); 131 | * | if (deposit.account() == address(0)) { 132 | | revert Errors.EmptyDeposit(); 133 | | } 134 | | 135 | * | if (deposit.account() != msg.sender) { 136 | | revert Errors.Unauthorized(msg.sender, "account for cancelDeposit"); 137 | | } 138 | | 139 | * | depositHandler.cancelDeposit(key); 140 | | } 141 | | 142 | | function simulateExecuteDeposit( 143 | | bytes32 key, 144 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams 145 | | ) external payable nonReentrant { 146 | | depositHandler.simulateExecuteDeposit(key, simulatedOracleParams); 147 | | } 148 | | 149 | * | function createWithdrawal( 150 | | WithdrawalUtils.CreateWithdrawalParams calldata params 151 | * | ) external payable override nonReentrant returns (bytes32) { 152 | * | address account = msg.sender; 153 | | 154 | * | return withdrawalHandler.createWithdrawal(account, params); 155 | | } 156 | | 157 | * | function cancelWithdrawal( 158 | | bytes32 key 159 | * | ) external payable override nonReentrant { 160 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get( 161 | * | dataStore, 162 | * | key 163 | | ); 164 | * | if (withdrawal.account() != msg.sender) { 165 | * | revert Errors.Unauthorized( 166 | * | msg.sender, 167 | | "account for cancelWithdrawal" 168 | | ); 169 | | } 170 | | 171 | * | withdrawalHandler.cancelWithdrawal(key); 172 | | } 173 | | 174 | * | function executeAtomicWithdrawal( 175 | | WithdrawalUtils.CreateWithdrawalParams calldata params, 176 | | OracleUtils.SetPricesParams calldata oracleParams 177 | | ) external payable override nonReentrant { 178 | * | address account = msg.sender; 179 | | 180 | | return 181 | * | withdrawalHandler.executeAtomicWithdrawal( 182 | * | account, 183 | * | params, 184 | * | oracleParams 185 | | ); 186 | | } 187 | | 188 | | function simulateExecuteWithdrawal( 189 | | bytes32 key, 190 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams, 191 | | ISwapPricingUtils.SwapPricingType swapPricingType 192 | | ) external payable nonReentrant { 193 | | withdrawalHandler.simulateExecuteWithdrawal( 194 | | key, 195 | | simulatedOracleParams, 196 | | swapPricingType 197 | | ); 198 | | } 199 | | 200 | | function createShift( 201 | | ShiftUtils.CreateShiftParams calldata params 202 | | ) external payable override nonReentrant returns (bytes32) { 203 | | address account = msg.sender; 204 | | 205 | | return shiftHandler.createShift(account, params); 206 | | } 207 | | 208 | | function cancelShift(bytes32 key) external payable override nonReentrant { 209 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key); 210 | | if (shift.account() != msg.sender) { 211 | | revert Errors.Unauthorized(msg.sender, "account for cancelShift"); 212 | | } 213 | | 214 | | shiftHandler.cancelShift(key); 215 | | } 216 | | 217 | | function simulateExecuteShift( 218 | | bytes32 key, 219 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams 220 | | ) external payable nonReentrant { 221 | | shiftHandler.simulateExecuteShift(key, simulatedOracleParams); 222 | | } 223 | | 224 | | /** 225 | | * @dev Creates a new order with the given amount, order parameters. The order is 226 | | * created by transferring the specified amount of collateral tokens from the caller's account to the 227 | | * order store, and then calling the `createOrder()` function on the order handler contract. The 228 | | * referral code is also set on the caller's account using the referral storage contract. 229 | | */ 230 | * | function createOrder( 231 | | IBaseOrderUtils.CreateOrderParams calldata params 232 | * | ) external payable override nonReentrant returns (bytes32) { 233 | * | address account = msg.sender; 234 | | 235 | * | return orderHandler.createOrder(account, params); 236 | | } 237 | | 238 | | //NOTE: FUZZ change 239 | | 240 | * | function createOrderFUZZ( 241 | | IBaseOrderUtils.CreateOrderParams calldata params 242 | | ) 243 | | external 244 | | payable 245 | | override 246 | | nonReentrant 247 | * | returns (bool success, bytes32 key) 248 | | { 249 | * | address account = msg.sender; 250 | | 251 | * | try orderHandler.createOrder(account, params) returns ( 252 | | bytes32 returnKey 253 | | ) { 254 | * | key = returnKey; 255 | * | success = true; 256 | | } catch {} 257 | | 258 | * | return (success, key); 259 | | } 260 | | 261 | | function setSavedCallbackContract( 262 | | address market, 263 | | address callbackContract 264 | | ) external payable nonReentrant { 265 | | // save the callback contract based on the account and market so that 266 | | // it can be called on liquidations and ADLs 267 | | CallbackUtils.setSavedCallbackContract( 268 | | dataStore, 269 | | msg.sender, // account 270 | | market, 271 | | callbackContract 272 | | ); 273 | | } 274 | | 275 | | /** 276 | | * @dev Updates the given order with the specified size delta, acceptable price, and trigger price. 277 | | * The `updateOrder()` feature must be enabled for the given order type. The caller must be the owner 278 | | * of the order, and the order must not be a market order. The size delta, trigger price, and 279 | | * acceptable price are updated on the order, and the order is unfrozen. Any additional WNT that is 280 | | * transferred to the contract is added to the order's execution fee. The updated order is then saved 281 | | * in the order store, and an `OrderUpdated` event is emitted. 282 | | * 283 | | * @param key The unique ID of the order to be updated 284 | | * @param sizeDeltaUsd The new size delta for the order 285 | | * @param acceptablePrice The new acceptable price for the order 286 | | * @param triggerPrice The new trigger price for the order 287 | | */ 288 | | function updateOrder( 289 | | bytes32 key, 290 | | uint256 sizeDeltaUsd, 291 | | uint256 acceptablePrice, 292 | | uint256 triggerPrice, 293 | | uint256 minOutputAmount, 294 | | bool autoCancel 295 | | ) external payable nonReentrant { 296 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 297 | | if (order.account() != msg.sender) { 298 | | revert Errors.Unauthorized(msg.sender, "account for updateOrder"); 299 | | } 300 | | 301 | | orderHandler.updateOrder( 302 | | key, 303 | | sizeDeltaUsd, 304 | | acceptablePrice, 305 | | triggerPrice, 306 | | minOutputAmount, 307 | | autoCancel, 308 | | order 309 | | ); 310 | | } 311 | | 312 | | /** 313 | | * @dev Cancels the given order. The `cancelOrder()` feature must be enabled for the given order 314 | | * type. The caller must be the owner of the order, and the order must not be a market order. The 315 | | * order is cancelled by calling the `cancelOrder()` function in the `OrderUtils` contract. This 316 | | * function also records the starting gas amount and the reason for cancellation, which is passed to 317 | | * the `cancelOrder()` function. 318 | | * 319 | | * @param key The unique ID of the order to be cancelled 320 | | */ 321 | * | function cancelOrder(bytes32 key) external payable nonReentrant { 322 | * | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 323 | * | if (order.account() == address(0)) { 324 | | revert Errors.EmptyOrder(); 325 | | } 326 | | 327 | * | if (order.account() != msg.sender) { 328 | | revert Errors.Unauthorized(msg.sender, "account for cancelOrder"); 329 | | } 330 | | 331 | * | orderHandler.cancelOrder(key); 332 | | } 333 | | 334 | | function simulateExecuteOrder( 335 | | bytes32 key, 336 | | OracleUtils.SimulatePricesParams memory simulatedOracleParams 337 | | ) external payable nonReentrant { 338 | | orderHandler.simulateExecuteOrder(key, simulatedOracleParams); 339 | | } 340 | | 341 | | /** 342 | | * @dev Claims funding fees for the given markets and tokens on behalf of the caller, and sends the 343 | | * fees to the specified receiver. The length of the `markets` and `tokens` arrays must be the same. 344 | | * For each market-token pair, the `claimFundingFees()` function in the `MarketUtils` contract is 345 | | * called to claim the fees for the caller. 346 | | * 347 | | * @param markets An array of market addresses 348 | | * @param tokens An array of token addresses, corresponding to the given markets 349 | | * @param receiver The address to which the claimed fees should be sent 350 | | */ 351 | * | function claimFundingFees( 352 | | address[] memory markets, 353 | | address[] memory tokens, 354 | | address receiver 355 | * | ) external payable nonReentrant returns (uint256[] memory) { 356 | * | if (markets.length != tokens.length) { 357 | | revert Errors.InvalidClaimFundingFeesInput( 358 | | markets.length, 359 | | tokens.length 360 | | ); 361 | | } 362 | | 363 | * | FeatureUtils.validateFeature( 364 | * | dataStore, 365 | * | Keys.claimFundingFeesFeatureDisabledKey(address(this)) 366 | | ); 367 | | 368 | * | AccountUtils.validateReceiver(receiver); 369 | | 370 | * | address account = msg.sender; 371 | | 372 | * | uint256[] memory claimedAmounts = new uint256[](markets.length); 373 | | 374 | * | for (uint256 i; i < markets.length; i++) { 375 | * | claimedAmounts[i] = MarketUtils.claimFundingFees( 376 | * | dataStore, 377 | * | eventEmitter, 378 | * | markets[i], 379 | * | tokens[i], 380 | * | account, 381 | * | receiver 382 | | ); 383 | | } 384 | | 385 | * | return claimedAmounts; 386 | | } 387 | | 388 | | function claimCollateral( 389 | | address[] memory markets, 390 | | address[] memory tokens, 391 | | uint256[] memory timeKeys, 392 | | address receiver 393 | | ) external payable nonReentrant returns (uint256[] memory) { 394 | | if ( 395 | | markets.length != tokens.length || tokens.length != timeKeys.length 396 | | ) { 397 | | revert Errors.InvalidClaimCollateralInput( 398 | | markets.length, 399 | | tokens.length, 400 | | timeKeys.length 401 | | ); 402 | | } 403 | | 404 | | FeatureUtils.validateFeature( 405 | | dataStore, 406 | | Keys.claimCollateralFeatureDisabledKey(address(this)) 407 | | ); 408 | | 409 | | AccountUtils.validateReceiver(receiver); 410 | | 411 | | address account = msg.sender; 412 | | 413 | | uint256[] memory claimedAmounts = new uint256[](markets.length); 414 | | 415 | | for (uint256 i; i < markets.length; i++) { 416 | | claimedAmounts[i] = MarketUtils.claimCollateral( 417 | | dataStore, 418 | | eventEmitter, 419 | | markets[i], 420 | | tokens[i], 421 | | timeKeys[i], 422 | | account, 423 | | receiver 424 | | ); 425 | | } 426 | | 427 | | return claimedAmounts; 428 | | } 429 | | 430 | | /** 431 | | * @dev Claims affiliate rewards for the given markets and tokens on behalf of the caller, and sends 432 | | * the rewards to the specified receiver. The length of the `markets` and `tokens` arrays must be 433 | | * the same. For each market-token pair, the `claimAffiliateReward()` function in the `ReferralUtils` 434 | | * contract is called to claim the rewards for the caller. 435 | | * 436 | | * @param markets An array of market addresses 437 | | * @param tokens An array of token addresses, corresponding to the given markets 438 | | * @param receiver The address to which the claimed rewards should be sent 439 | | */ 440 | | function claimAffiliateRewards( 441 | | address[] memory markets, 442 | | address[] memory tokens, 443 | | address receiver 444 | | ) external payable nonReentrant returns (uint256[] memory) { 445 | | if (markets.length != tokens.length) { 446 | | revert Errors.InvalidClaimAffiliateRewardsInput( 447 | | markets.length, 448 | | tokens.length 449 | | ); 450 | | } 451 | | 452 | | FeatureUtils.validateFeature( 453 | | dataStore, 454 | | Keys.claimAffiliateRewardsFeatureDisabledKey(address(this)) 455 | | ); 456 | | 457 | | address account = msg.sender; 458 | | 459 | | uint256[] memory claimedAmounts = new uint256[](markets.length); 460 | | 461 | | for (uint256 i; i < markets.length; i++) { 462 | | claimedAmounts[i] = ReferralUtils.claimAffiliateReward( 463 | | dataStore, 464 | | eventEmitter, 465 | | markets[i], 466 | | tokens[i], 467 | | account, 468 | | receiver 469 | | ); 470 | | } 471 | | 472 | | return claimedAmounts; 473 | | } 474 | | 475 | | function setUiFeeFactor(uint256 uiFeeFactor) external payable nonReentrant { 476 | | address account = msg.sender; 477 | | MarketUtils.setUiFeeFactor( 478 | | dataStore, 479 | | eventEmitter, 480 | | account, 481 | | uiFeeFactor 482 | | ); 483 | | } 484 | | 485 | | function claimUiFees( 486 | | address[] memory markets, 487 | | address[] memory tokens, 488 | | address receiver 489 | | ) external payable nonReentrant returns (uint256[] memory) { 490 | | if (markets.length != tokens.length) { 491 | | revert Errors.InvalidClaimUiFeesInput( 492 | | markets.length, 493 | | tokens.length 494 | | ); 495 | | } 496 | | 497 | | FeatureUtils.validateFeature( 498 | | dataStore, 499 | | Keys.claimUiFeesFeatureDisabledKey(address(this)) 500 | | ); 501 | | 502 | | address uiFeeReceiver = msg.sender; 503 | | 504 | | uint256[] memory claimedAmounts = new uint256[](markets.length); 505 | | 506 | | for (uint256 i; i < markets.length; i++) { 507 | | claimedAmounts[i] = FeeUtils.claimUiFees( 508 | | dataStore, 509 | | eventEmitter, 510 | | uiFeeReceiver, 511 | | markets[i], 512 | | tokens[i], 513 | | receiver 514 | | ); 515 | | } 516 | | 517 | | return claimedAmounts; 518 | | } 519 | | } 520 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/IExchangeRouter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../exchange/IDepositHandler.sol"; 6 | | import "../exchange/IWithdrawalHandler.sol"; 7 | | import "../exchange/IShiftHandler.sol"; 8 | | import "../exchange/IOrderHandler.sol"; 9 | | import "../exchange/IGlvHandler.sol"; 10 | | 11 | | interface IExchangeRouter { 12 | | function createDeposit( 13 | | DepositUtils.CreateDepositParams calldata params 14 | | ) external payable returns (bytes32); 15 | | 16 | | function cancelDeposit(bytes32 key) external payable; 17 | | 18 | | function createWithdrawal( 19 | | WithdrawalUtils.CreateWithdrawalParams calldata params 20 | | ) external payable returns (bytes32); 21 | | 22 | | function cancelWithdrawal(bytes32 key) external payable; 23 | | 24 | | function executeAtomicWithdrawal( 25 | | WithdrawalUtils.CreateWithdrawalParams calldata params, 26 | | OracleUtils.SetPricesParams calldata oracleParams 27 | | ) external payable; 28 | | 29 | | function createShift( 30 | | ShiftUtils.CreateShiftParams calldata params 31 | | ) external payable returns (bytes32); 32 | | 33 | | function cancelShift(bytes32 key) external payable; 34 | | 35 | | function createOrder( 36 | | IBaseOrderUtils.CreateOrderParams calldata params 37 | | ) external payable returns (bytes32); 38 | | 39 | | //FUZZ ADDED 40 | | function createOrderFUZZ( 41 | | IBaseOrderUtils.CreateOrderParams calldata params 42 | | ) external payable returns (bool, bytes32); 43 | | 44 | | function updateOrder( 45 | | bytes32 key, 46 | | uint256 sizeDeltaUsd, 47 | | uint256 acceptablePrice, 48 | | uint256 triggerPrice, 49 | | uint256 minOutputAmount, 50 | | bool autoCancel 51 | | ) external payable; 52 | | 53 | | function cancelOrder(bytes32 key) external payable; 54 | | } 55 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/Router.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 7 | | 8 | | import "../role/RoleModule.sol"; 9 | | 10 | | /** 11 | | * @title Router 12 | | * @dev Users will approve this router for token spenditures 13 | | */ 14 | * | contract Router is RoleModule { 15 | | using SafeERC20 for IERC20; 16 | | 17 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {} 18 | | 19 | | /** 20 | | * @dev transfer the specified amount of tokens from the account to the receiver 21 | | * @param token the token to transfer 22 | | * @param account the account to transfer from 23 | | * @param receiver the account to transfer to 24 | | * @param amount the amount of tokens to transfer 25 | | */ 26 | * | function pluginTransfer(address token, address account, address receiver, uint256 amount) external onlyRouterPlugin { 27 | * | IERC20(token).safeTransferFrom(account, receiver, amount); 28 | | } 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/router/SubaccountRouter.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./BaseRouter.sol"; 6 | | import "../exchange/IOrderHandler.sol"; 7 | | import "../feature/FeatureUtils.sol"; 8 | | import "../subaccount/SubaccountUtils.sol"; 9 | | import "../order/OrderVault.sol"; 10 | | import "../order/OrderStoreUtils.sol"; 11 | | 12 | * | contract SubaccountRouter is BaseRouter { 13 | | using EventUtils for EventUtils.AddressItems; 14 | | using EventUtils for EventUtils.UintItems; 15 | | using EventUtils for EventUtils.IntItems; 16 | | using EventUtils for EventUtils.BoolItems; 17 | | using EventUtils for EventUtils.Bytes32Items; 18 | | using EventUtils for EventUtils.BytesItems; 19 | | using EventUtils for EventUtils.StringItems; 20 | | 21 | | using Order for Order.Props; 22 | | 23 | | IOrderHandler public immutable orderHandler; 24 | | OrderVault public immutable orderVault; 25 | | 26 | | constructor( 27 | | Router _router, 28 | | RoleStore _roleStore, 29 | | DataStore _dataStore, 30 | | EventEmitter _eventEmitter, 31 | | IOrderHandler _orderHandler, 32 | | OrderVault _orderVault 33 | | ) BaseRouter(_router, _roleStore, _dataStore, _eventEmitter) { 34 | | orderHandler = _orderHandler; 35 | | orderVault = _orderVault; 36 | | } 37 | | 38 | | receive() external payable { 39 | | address wnt = TokenUtils.wnt(dataStore); 40 | | if (msg.sender != wnt) { 41 | | revert Errors.InvalidNativeTokenSender(msg.sender); 42 | | } 43 | | } 44 | | 45 | | function addSubaccount(address subaccount) external payable nonReentrant { 46 | | address account = msg.sender; 47 | | SubaccountUtils.addSubaccount(dataStore, eventEmitter, account, subaccount); 48 | | } 49 | | 50 | | function removeSubaccount(address subaccount) external payable nonReentrant { 51 | | address account = msg.sender; 52 | | SubaccountUtils.removeSubaccount(dataStore, eventEmitter, account, subaccount); 53 | | } 54 | | 55 | | function setMaxAllowedSubaccountActionCount( 56 | | address subaccount, 57 | | bytes32 actionType, 58 | | uint256 maxAllowedCount 59 | | ) external payable nonReentrant { 60 | | address account = msg.sender; 61 | | 62 | | SubaccountUtils.setMaxAllowedSubaccountActionCount( 63 | | dataStore, 64 | | eventEmitter, 65 | | account, 66 | | subaccount, 67 | | actionType, 68 | | maxAllowedCount 69 | | ); 70 | | } 71 | | 72 | | function setSubaccountAutoTopUpAmount( 73 | | address subaccount, 74 | | uint256 amount 75 | | ) external payable nonReentrant { 76 | | address account = msg.sender; 77 | | 78 | | SubaccountUtils.setSubaccountAutoTopUpAmount( 79 | | dataStore, 80 | | eventEmitter, 81 | | account, 82 | | subaccount, 83 | | amount 84 | | ); 85 | | } 86 | | 87 | | function createOrder( 88 | | address account, 89 | | IBaseOrderUtils.CreateOrderParams calldata params 90 | | ) external payable nonReentrant returns (bytes32) { 91 | | uint256 startingGas = gasleft(); 92 | | 93 | | _handleSubaccountAction(account, Keys.SUBACCOUNT_ORDER_ACTION); 94 | | 95 | | if (params.addresses.receiver != account) { 96 | | revert Errors.InvalidReceiverForSubaccountOrder(params.addresses.receiver, account); 97 | | } 98 | | 99 | | if ( 100 | | params.orderType == Order.OrderType.MarketSwap || 101 | | params.orderType == Order.OrderType.LimitSwap || 102 | | params.orderType == Order.OrderType.MarketIncrease || 103 | | params.orderType == Order.OrderType.LimitIncrease 104 | | ) { 105 | | router.pluginTransfer( 106 | | params.addresses.initialCollateralToken, // token 107 | | account, // account 108 | | address(orderVault), // receiver 109 | | params.numbers.initialCollateralDeltaAmount // amount 110 | | ); 111 | | } 112 | | 113 | | bytes32 key = orderHandler.createOrder( 114 | | account, 115 | | params 116 | | ); 117 | | 118 | | _autoTopUpSubaccount( 119 | | account, // account 120 | | msg.sender, // subaccount 121 | | startingGas, // startingGas 122 | | params.numbers.executionFee // executionFee 123 | | ); 124 | | 125 | | return key; 126 | | } 127 | | 128 | | function updateOrder( 129 | | bytes32 key, 130 | | uint256 sizeDeltaUsd, 131 | | uint256 acceptablePrice, 132 | | uint256 triggerPrice, 133 | | uint256 minOutputAmount, 134 | | bool autoCancel 135 | | ) external payable nonReentrant { 136 | | uint256 startingGas = gasleft(); 137 | | 138 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 139 | | 140 | | if (order.account() == address(0)) { revert Errors.EmptyOrder(); } 141 | | 142 | | _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION); 143 | | 144 | | orderHandler.updateOrder( 145 | | key, 146 | | sizeDeltaUsd, 147 | | acceptablePrice, 148 | | triggerPrice, 149 | | minOutputAmount, 150 | | autoCancel, 151 | | order 152 | | ); 153 | | 154 | | _autoTopUpSubaccount( 155 | | order.account(), // account 156 | | msg.sender, // subaccount 157 | | startingGas, // startingGas 158 | | 0 // executionFee 159 | | ); 160 | | } 161 | | 162 | | function cancelOrder( 163 | | bytes32 key 164 | | ) external payable nonReentrant { 165 | | uint256 startingGas = gasleft(); 166 | | 167 | | Order.Props memory order = OrderStoreUtils.get(dataStore, key); 168 | | 169 | | if (order.account() == address(0)) { revert Errors.EmptyOrder(); } 170 | | 171 | | _handleSubaccountAction(order.account(), Keys.SUBACCOUNT_ORDER_ACTION); 172 | | 173 | | orderHandler.cancelOrder(key); 174 | | 175 | | _autoTopUpSubaccount( 176 | | order.account(), // account 177 | | msg.sender, // subaccount 178 | | startingGas, // startingGas 179 | | 0 // executionFee 180 | | ); 181 | | } 182 | | 183 | | function _handleSubaccountAction(address account, bytes32 actionType) internal { 184 | | FeatureUtils.validateFeature(dataStore, Keys.subaccountFeatureDisabledKey(address(this))); 185 | | 186 | | address subaccount = msg.sender; 187 | | SubaccountUtils.validateSubaccount(dataStore, account, subaccount); 188 | | 189 | | SubaccountUtils.incrementSubaccountActionCount( 190 | | dataStore, 191 | | eventEmitter, 192 | | account, 193 | | subaccount, 194 | | actionType 195 | | ); 196 | | } 197 | | 198 | | // the subaccount is topped up with wrapped native tokens 199 | | // the subaccount should separately unwrap the token as needed 200 | | function _autoTopUpSubaccount(address account, address subaccount, uint256 startingGas, uint256 executionFee) internal { 201 | | uint256 amount = SubaccountUtils.getSubaccountAutoTopUpAmount(dataStore, account, subaccount); 202 | | if (amount == 0) { 203 | | return; 204 | | } 205 | | 206 | | IERC20 wnt = IERC20(dataStore.getAddress(Keys.WNT)); 207 | | 208 | | if (wnt.allowance(account, address(router)) < amount) { return; } 209 | | if (wnt.balanceOf(account) < amount) { return; } 210 | | 211 | | // cap the top up amount to the amount of native tokens used 212 | | uint256 nativeTokensUsed = (startingGas - gasleft()) * tx.gasprice + executionFee; 213 | | if (nativeTokensUsed < amount) { amount = nativeTokensUsed; } 214 | | 215 | | router.pluginTransfer( 216 | | address(wnt), // token 217 | | account, // account 218 | | address(this), // receiver 219 | | amount // amount 220 | | ); 221 | | 222 | | TokenUtils.withdrawAndSendNativeToken( 223 | | dataStore, 224 | | address(wnt), 225 | | subaccount, 226 | | amount 227 | | ); 228 | | 229 | | EventUtils.EventLogData memory eventData; 230 | | 231 | | eventData.addressItems.initItems(2); 232 | | eventData.addressItems.setItem(0, "account", account); 233 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 234 | | 235 | | eventData.uintItems.initItems(1); 236 | | eventData.uintItems.setItem(0, "amount", amount); 237 | | 238 | | eventEmitter.emitEventLog2( 239 | | "SubaccountAutoTopUp", 240 | | Cast.toBytes32(account), 241 | | Cast.toBytes32(subaccount), 242 | | eventData 243 | | ); 244 | | } 245 | | } 246 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/Shift.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | * | library Shift { 6 | | struct Props { 7 | | Addresses addresses; 8 | | Numbers numbers; 9 | | } 10 | | 11 | | struct Addresses { 12 | | address account; 13 | | address receiver; 14 | | address callbackContract; 15 | | address uiFeeReceiver; 16 | | address fromMarket; 17 | | address toMarket; 18 | | } 19 | | 20 | | struct Numbers { 21 | | uint256 marketTokenAmount; 22 | | uint256 minMarketTokens; 23 | | uint256 updatedAtTime; 24 | | uint256 executionFee; 25 | | uint256 callbackGasLimit; 26 | | } 27 | | 28 | | function account(Props memory props) internal pure returns (address) { 29 | | return props.addresses.account; 30 | | } 31 | | 32 | | function setAccount(Props memory props, address value) internal pure { 33 | | props.addresses.account = value; 34 | | } 35 | | 36 | | function receiver(Props memory props) internal pure returns (address) { 37 | | return props.addresses.receiver; 38 | | } 39 | | 40 | | function setReceiver(Props memory props, address value) internal pure { 41 | | props.addresses.receiver = value; 42 | | } 43 | | 44 | | function callbackContract(Props memory props) internal pure returns (address) { 45 | | return props.addresses.callbackContract; 46 | | } 47 | | 48 | | function setCallbackContract(Props memory props, address value) internal pure { 49 | | props.addresses.callbackContract = value; 50 | | } 51 | | 52 | | function uiFeeReceiver(Props memory props) internal pure returns (address) { 53 | | return props.addresses.uiFeeReceiver; 54 | | } 55 | | 56 | | function setUiFeeReceiver(Props memory props, address value) internal pure { 57 | | props.addresses.uiFeeReceiver = value; 58 | | } 59 | | 60 | | function fromMarket(Props memory props) internal pure returns (address) { 61 | | return props.addresses.fromMarket; 62 | | } 63 | | 64 | | function setFromMarket(Props memory props, address value) internal pure { 65 | | props.addresses.fromMarket = value; 66 | | } 67 | | 68 | | function toMarket(Props memory props) internal pure returns (address) { 69 | | return props.addresses.toMarket; 70 | | } 71 | | 72 | | function setToMarket(Props memory props, address value) internal pure { 73 | | props.addresses.toMarket = value; 74 | | } 75 | | 76 | | function marketTokenAmount(Props memory props) internal pure returns (uint256) { 77 | | return props.numbers.marketTokenAmount; 78 | | } 79 | | 80 | | function setMarketTokenAmount(Props memory props, uint256 value) internal pure { 81 | | props.numbers.marketTokenAmount = value; 82 | | } 83 | | 84 | | function minMarketTokens(Props memory props) internal pure returns (uint256) { 85 | | return props.numbers.minMarketTokens; 86 | | } 87 | | 88 | | function setMinMarketTokens(Props memory props, uint256 value) internal pure { 89 | | props.numbers.minMarketTokens = value; 90 | | } 91 | | 92 | | function updatedAtTime(Props memory props) internal pure returns (uint256) { 93 | | return props.numbers.updatedAtTime; 94 | | } 95 | | 96 | | function setUpdatedAtTime(Props memory props, uint256 value) internal pure { 97 | | props.numbers.updatedAtTime = value; 98 | | } 99 | | 100 | | function executionFee(Props memory props) internal pure returns (uint256) { 101 | | return props.numbers.executionFee; 102 | | } 103 | | 104 | | function setExecutionFee(Props memory props, uint256 value) internal pure { 105 | | props.numbers.executionFee = value; 106 | | } 107 | | 108 | | function callbackGasLimit(Props memory props) internal pure returns (uint256) { 109 | | return props.numbers.callbackGasLimit; 110 | | } 111 | | 112 | | function setCallbackGasLimit(Props memory props, uint256 value) internal pure { 113 | | props.numbers.callbackGasLimit = value; 114 | | } 115 | | 116 | | } 117 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./Shift.sol"; 10 | | 11 | * | library ShiftEventUtils { 12 | | using Shift for Shift.Props; 13 | | 14 | | using EventUtils for EventUtils.AddressItems; 15 | | using EventUtils for EventUtils.UintItems; 16 | | using EventUtils for EventUtils.IntItems; 17 | | using EventUtils for EventUtils.BoolItems; 18 | | using EventUtils for EventUtils.Bytes32Items; 19 | | using EventUtils for EventUtils.BytesItems; 20 | | using EventUtils for EventUtils.StringItems; 21 | | 22 | | function emitShiftCreated( 23 | | EventEmitter eventEmitter, 24 | | bytes32 key, 25 | | Shift.Props memory shift 26 | | ) internal { 27 | | EventUtils.EventLogData memory eventData; 28 | | 29 | | eventData.addressItems.initItems(5); 30 | | eventData.addressItems.setItem(0, "account", shift.account()); 31 | | eventData.addressItems.setItem(1, "receiver", shift.receiver()); 32 | | eventData.addressItems.setItem(2, "callbackContract", shift.callbackContract()); 33 | | eventData.addressItems.setItem(3, "fromMarket", shift.fromMarket()); 34 | | eventData.addressItems.setItem(4, "toMarket", shift.toMarket()); 35 | | 36 | | eventData.uintItems.initItems(5); 37 | | eventData.uintItems.setItem(0, "marketTokenAmount", shift.marketTokenAmount()); 38 | | eventData.uintItems.setItem(1, "minMarketTokens", shift.minMarketTokens()); 39 | | eventData.uintItems.setItem(2, "updatedAtTime", shift.updatedAtTime()); 40 | | eventData.uintItems.setItem(3, "executionFee", shift.executionFee()); 41 | | eventData.uintItems.setItem(4, "callbackGasLimit", shift.callbackGasLimit()); 42 | | 43 | | eventData.bytes32Items.initItems(1); 44 | | eventData.bytes32Items.setItem(0, "key", key); 45 | | 46 | | eventEmitter.emitEventLog2( 47 | | "ShiftCreated", 48 | | key, 49 | | Cast.toBytes32(shift.account()), 50 | | eventData 51 | | ); 52 | | } 53 | | 54 | | function emitShiftExecuted( 55 | | EventEmitter eventEmitter, 56 | | bytes32 key, 57 | | address account, 58 | | uint256 receivedMarketTokens 59 | | ) internal { 60 | | EventUtils.EventLogData memory eventData; 61 | | 62 | | eventData.bytes32Items.initItems(1); 63 | | eventData.bytes32Items.setItem(0, "key", key); 64 | | 65 | | eventData.addressItems.initItems(1); 66 | | eventData.addressItems.setItem(0, "account", account); 67 | | 68 | | eventData.uintItems.initItems(1); 69 | | eventData.uintItems.setItem(0, "receivedMarketTokens", receivedMarketTokens); 70 | | 71 | | eventEmitter.emitEventLog2( 72 | | "ShiftExecuted", 73 | | key, 74 | | Cast.toBytes32(account), 75 | | eventData 76 | | ); 77 | | } 78 | | 79 | | function emitShiftCancelled( 80 | | EventEmitter eventEmitter, 81 | | bytes32 key, 82 | | address account, 83 | | string memory reason, 84 | | bytes memory reasonBytes 85 | | ) internal { 86 | | EventUtils.EventLogData memory eventData; 87 | | 88 | | eventData.bytes32Items.initItems(1); 89 | | eventData.bytes32Items.setItem(0, "key", key); 90 | | 91 | | eventData.addressItems.initItems(1); 92 | | eventData.addressItems.setItem(0, "account", account); 93 | | 94 | | eventData.stringItems.initItems(1); 95 | | eventData.stringItems.setItem(0, "reason", reason); 96 | | 97 | | eventData.bytesItems.initItems(1); 98 | | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 99 | | 100 | | eventEmitter.emitEventLog2( 101 | | "ShiftCancelled", 102 | | key, 103 | | Cast.toBytes32(account), 104 | | eventData 105 | | ); 106 | | } 107 | | } 108 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Shift.sol"; 9 | | 10 | * | library ShiftStoreUtils { 11 | | using Shift for Shift.Props; 12 | | 13 | | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 14 | | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER")); 15 | | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT")); 16 | | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER")); 17 | | bytes32 internal constant FROM_MARKET = keccak256(abi.encode("FROM_MARKET")); 18 | | bytes32 internal constant TO_MARKET = keccak256(abi.encode("TO_MARKET")); 19 | | 20 | | bytes32 internal constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode("MARKET_TOKEN_AMOUNT")); 21 | | bytes32 internal constant MIN_MARKET_TOKENS = keccak256(abi.encode("MIN_MARKET_TOKENS")); 22 | | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME")); 23 | | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE")); 24 | | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT")); 25 | | 26 | | function get(DataStore dataStore, bytes32 key) internal view returns (Shift.Props memory) { 27 | | Shift.Props memory shift; 28 | | if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) { 29 | | return shift; 30 | | } 31 | | 32 | | shift.setAccount(dataStore.getAddress( 33 | | keccak256(abi.encode(key, ACCOUNT)) 34 | | )); 35 | | 36 | | shift.setReceiver(dataStore.getAddress( 37 | | keccak256(abi.encode(key, RECEIVER)) 38 | | )); 39 | | 40 | | shift.setCallbackContract(dataStore.getAddress( 41 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 42 | | )); 43 | | 44 | | shift.setUiFeeReceiver(dataStore.getAddress( 45 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 46 | | )); 47 | | 48 | | shift.setFromMarket(dataStore.getAddress( 49 | | keccak256(abi.encode(key, FROM_MARKET)) 50 | | )); 51 | | 52 | | shift.setToMarket(dataStore.getAddress( 53 | | keccak256(abi.encode(key, TO_MARKET)) 54 | | )); 55 | | 56 | | shift.setMarketTokenAmount(dataStore.getUint( 57 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)) 58 | | )); 59 | | 60 | | shift.setMinMarketTokens(dataStore.getUint( 61 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS)) 62 | | )); 63 | | 64 | | shift.setUpdatedAtTime(dataStore.getUint( 65 | | keccak256(abi.encode(key, UPDATED_AT_TIME)) 66 | | )); 67 | | 68 | | shift.setExecutionFee(dataStore.getUint( 69 | | keccak256(abi.encode(key, EXECUTION_FEE)) 70 | | )); 71 | | 72 | | shift.setCallbackGasLimit(dataStore.getUint( 73 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 74 | | )); 75 | | 76 | | return shift; 77 | | } 78 | | 79 | | function set(DataStore dataStore, bytes32 key, Shift.Props memory shift) internal { 80 | | dataStore.addBytes32( 81 | | Keys.SHIFT_LIST, 82 | | key 83 | | ); 84 | | 85 | | dataStore.addBytes32( 86 | | Keys.accountShiftListKey(shift.account()), 87 | | key 88 | | ); 89 | | 90 | | dataStore.setAddress( 91 | | keccak256(abi.encode(key, ACCOUNT)), 92 | | shift.account() 93 | | ); 94 | | 95 | | dataStore.setAddress( 96 | | keccak256(abi.encode(key, RECEIVER)), 97 | | shift.receiver() 98 | | ); 99 | | 100 | | dataStore.setAddress( 101 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)), 102 | | shift.callbackContract() 103 | | ); 104 | | 105 | | dataStore.setAddress( 106 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)), 107 | | shift.uiFeeReceiver() 108 | | ); 109 | | 110 | | dataStore.setAddress( 111 | | keccak256(abi.encode(key, FROM_MARKET)), 112 | | shift.fromMarket() 113 | | ); 114 | | 115 | | dataStore.setAddress( 116 | | keccak256(abi.encode(key, TO_MARKET)), 117 | | shift.toMarket() 118 | | ); 119 | | 120 | | dataStore.setUint( 121 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)), 122 | | shift.marketTokenAmount() 123 | | ); 124 | | 125 | | dataStore.setUint( 126 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS)), 127 | | shift.minMarketTokens() 128 | | ); 129 | | 130 | | dataStore.setUint( 131 | | keccak256(abi.encode(key, UPDATED_AT_TIME)), 132 | | shift.updatedAtTime() 133 | | ); 134 | | 135 | | dataStore.setUint( 136 | | keccak256(abi.encode(key, EXECUTION_FEE)), 137 | | shift.executionFee() 138 | | ); 139 | | 140 | | dataStore.setUint( 141 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)), 142 | | shift.callbackGasLimit() 143 | | ); 144 | | } 145 | | 146 | | function remove(DataStore dataStore, bytes32 key, address account) internal { 147 | | if (!dataStore.containsBytes32(Keys.SHIFT_LIST, key)) { 148 | | revert Errors.ShiftNotFound(key); 149 | | } 150 | | 151 | | dataStore.removeBytes32( 152 | | Keys.SHIFT_LIST, 153 | | key 154 | | ); 155 | | 156 | | dataStore.removeBytes32( 157 | | Keys.accountShiftListKey(account), 158 | | key 159 | | ); 160 | | 161 | | dataStore.removeAddress( 162 | | keccak256(abi.encode(key, ACCOUNT)) 163 | | ); 164 | | 165 | | dataStore.removeAddress( 166 | | keccak256(abi.encode(key, RECEIVER)) 167 | | ); 168 | | 169 | | dataStore.removeAddress( 170 | | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 171 | | ); 172 | | 173 | | dataStore.removeAddress( 174 | | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 175 | | ); 176 | | 177 | | dataStore.removeAddress( 178 | | keccak256(abi.encode(key, FROM_MARKET)) 179 | | ); 180 | | 181 | | dataStore.removeAddress( 182 | | keccak256(abi.encode(key, TO_MARKET)) 183 | | ); 184 | | 185 | | dataStore.removeUint( 186 | | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)) 187 | | ); 188 | | 189 | | dataStore.removeUint( 190 | | keccak256(abi.encode(key, MIN_MARKET_TOKENS)) 191 | | ); 192 | | 193 | | dataStore.removeUint( 194 | | keccak256(abi.encode(key, UPDATED_AT_TIME)) 195 | | ); 196 | | 197 | | dataStore.removeUint( 198 | | keccak256(abi.encode(key, EXECUTION_FEE)) 199 | | ); 200 | | 201 | | dataStore.removeUint( 202 | | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 203 | | ); 204 | | } 205 | | 206 | | function getShiftCount(DataStore dataStore) internal view returns (uint256) { 207 | | return dataStore.getBytes32Count(Keys.SHIFT_LIST); 208 | | } 209 | | 210 | | function getShiftKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 211 | | return dataStore.getBytes32ValuesAt(Keys.SHIFT_LIST, start, end); 212 | | } 213 | | 214 | | function getAccountShiftCount(DataStore dataStore, address account) internal view returns (uint256) { 215 | | return dataStore.getBytes32Count(Keys.accountShiftListKey(account)); 216 | | } 217 | | 218 | | function getAccountShiftKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 219 | | return dataStore.getBytes32ValuesAt(Keys.accountShiftListKey(account), start, end); 220 | | } 221 | | } 222 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/DataStore.sol"; 6 | | import "../event/EventEmitter.sol"; 7 | | 8 | | import "./ShiftVault.sol"; 9 | | import "./ShiftStoreUtils.sol"; 10 | | import "./ShiftEventUtils.sol"; 11 | | 12 | | import "../nonce/NonceUtils.sol"; 13 | | 14 | | import "../gas/GasUtils.sol"; 15 | | import "../callback/CallbackUtils.sol"; 16 | | import "../utils/AccountUtils.sol"; 17 | | 18 | | import "../deposit/ExecuteDepositUtils.sol"; 19 | | import "../withdrawal/ExecuteWithdrawalUtils.sol"; 20 | | 21 | * | library ShiftUtils { 22 | | using Deposit for Deposit.Props; 23 | | using Withdrawal for Withdrawal.Props; 24 | | using Shift for Shift.Props; 25 | | 26 | | using EventUtils for EventUtils.AddressItems; 27 | | using EventUtils for EventUtils.UintItems; 28 | | using EventUtils for EventUtils.IntItems; 29 | | using EventUtils for EventUtils.BoolItems; 30 | | using EventUtils for EventUtils.Bytes32Items; 31 | | using EventUtils for EventUtils.BytesItems; 32 | | using EventUtils for EventUtils.StringItems; 33 | | 34 | | struct CreateShiftParams { 35 | | address receiver; 36 | | address callbackContract; 37 | | address uiFeeReceiver; 38 | | address fromMarket; 39 | | address toMarket; 40 | | uint256 minMarketTokens; 41 | | uint256 executionFee; 42 | | uint256 callbackGasLimit; 43 | | } 44 | | 45 | | struct CreateShiftCache { 46 | | uint256 estimatedGasLimit; 47 | | uint256 oraclePriceCount; 48 | | bytes32 key; 49 | | } 50 | | 51 | | struct ExecuteShiftParams { 52 | | DataStore dataStore; 53 | | EventEmitter eventEmitter; 54 | | ShiftVault shiftVault; 55 | | Oracle oracle; 56 | | bytes32 key; 57 | | address keeper; 58 | | uint256 startingGas; 59 | | } 60 | | 61 | | struct ExecuteShiftCache { 62 | | Withdrawal.Props withdrawal; 63 | | bytes32 withdrawalKey; 64 | | ExecuteWithdrawalUtils.ExecuteWithdrawalParams executeWithdrawalParams; 65 | | Market.Props depositMarket; 66 | | uint256 initialLongTokenAmount; 67 | | uint256 initialShortTokenAmount; 68 | | Deposit.Props deposit; 69 | | bytes32 depositKey; 70 | | ExecuteDepositUtils.ExecuteDepositParams executeDepositParams; 71 | | } 72 | | 73 | | function createShift( 74 | | DataStore dataStore, 75 | | EventEmitter eventEmitter, 76 | | ShiftVault shiftVault, 77 | | address account, 78 | | CreateShiftParams memory params 79 | | ) internal returns (bytes32) { 80 | | AccountUtils.validateAccount(account); 81 | | 82 | | if (params.fromMarket == params.toMarket) { 83 | | revert Errors.ShiftFromAndToMarketAreEqual(params.fromMarket); 84 | | } 85 | | 86 | | address wnt = TokenUtils.wnt(dataStore); 87 | | uint256 wntAmount = shiftVault.recordTransferIn(wnt); 88 | | 89 | | if (wntAmount < params.executionFee) { 90 | | revert Errors.InsufficientWntAmount(wntAmount, params.executionFee); 91 | | } 92 | | 93 | | AccountUtils.validateReceiver(params.receiver); 94 | | 95 | | uint256 marketTokenAmount = shiftVault.recordTransferIn(params.fromMarket); 96 | | 97 | | if (marketTokenAmount == 0) { 98 | | revert Errors.EmptyShiftAmount(); 99 | | } 100 | | 101 | | params.executionFee = wntAmount; 102 | | 103 | | Market.Props memory fromMarket = MarketUtils.getEnabledMarket(dataStore, params.fromMarket); 104 | | Market.Props memory toMarket = MarketUtils.getEnabledMarket(dataStore, params.toMarket); 105 | | 106 | | if (fromMarket.longToken != toMarket.longToken) { 107 | | revert Errors.LongTokensAreNotEqual(fromMarket.longToken, toMarket.longToken); 108 | | } 109 | | 110 | | if (fromMarket.shortToken != toMarket.shortToken) { 111 | | revert Errors.ShortTokensAreNotEqual(fromMarket.shortToken, toMarket.shortToken); 112 | | } 113 | | 114 | | MarketUtils.validateEnabledMarket(dataStore, params.fromMarket); 115 | | MarketUtils.validateEnabledMarket(dataStore, params.toMarket); 116 | | 117 | | Shift.Props memory shift = Shift.Props( 118 | | Shift.Addresses( 119 | | account, 120 | | params.receiver, 121 | | params.callbackContract, 122 | | params.uiFeeReceiver, 123 | | params.fromMarket, 124 | | params.toMarket 125 | | ), 126 | | Shift.Numbers( 127 | | marketTokenAmount, 128 | | params.minMarketTokens, 129 | | Chain.currentTimestamp(), 130 | | params.executionFee, 131 | | params.callbackGasLimit 132 | | ) 133 | | ); 134 | | 135 | | CallbackUtils.validateCallbackGasLimit(dataStore, shift.callbackGasLimit()); 136 | | 137 | | CreateShiftCache memory cache; 138 | | 139 | | cache.estimatedGasLimit = GasUtils.estimateExecuteShiftGasLimit(dataStore, shift); 140 | | cache.oraclePriceCount = GasUtils.estimateShiftOraclePriceCount(); 141 | | GasUtils.validateExecutionFee(dataStore, cache.estimatedGasLimit, params.executionFee, cache.oraclePriceCount); 142 | | 143 | | cache.key = NonceUtils.getNextKey(dataStore); 144 | | 145 | | ShiftStoreUtils.set(dataStore, cache.key, shift); 146 | | 147 | | ShiftEventUtils.emitShiftCreated(eventEmitter, cache.key, shift); 148 | | 149 | | return cache.key; 150 | | } 151 | | 152 | | function executeShift( 153 | | ExecuteShiftParams memory params, 154 | | Shift.Props memory shift 155 | | ) internal { 156 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 157 | | params.startingGas -= gasleft() / 63; 158 | | 159 | | ShiftStoreUtils.remove(params.dataStore, params.key, shift.account()); 160 | | 161 | | if (shift.account() == address(0)) { 162 | | revert Errors.EmptyShift(); 163 | | } 164 | | 165 | | if (shift.marketTokenAmount() == 0) { 166 | | revert Errors.EmptyShiftAmount(); 167 | | } 168 | | 169 | | ExecuteShiftCache memory cache; 170 | | 171 | | cache.depositMarket = MarketStoreUtils.get(params.dataStore, shift.toMarket()); 172 | | 173 | | // if a user sends tokens directly to the shiftVault 174 | | // the recordTransferIn after the shift withdrawal would record 175 | | // these additional tokens and perform a deposit on the combined 176 | | // token amount (tokens directly sent + tokens withdrawn) 177 | | // 178 | | // a user could use this to avoid paying deposit fees 179 | | // 180 | | // call shiftVault.recordTransferIn before the withdrawal to prevent 181 | | // this 182 | | params.shiftVault.recordTransferIn(cache.depositMarket.longToken); 183 | | params.shiftVault.recordTransferIn(cache.depositMarket.shortToken); 184 | | 185 | | cache.withdrawal = Withdrawal.Props( 186 | | Withdrawal.Addresses( 187 | | shift.account(), 188 | | address(params.shiftVault), // receiver 189 | | address(0), // callbackContract 190 | | shift.uiFeeReceiver(), // uiFeeReceiver 191 | | shift.fromMarket(), // market 192 | | new address[](0), // longTokenSwapPath 193 | | new address[](0) // shortTokenSwapPath 194 | | ), 195 | | Withdrawal.Numbers( 196 | | shift.marketTokenAmount(), 197 | | 0, // minLongTokenAmount 198 | | 0, // minShortTokenAmount 199 | | 0, // updatedAtBlock 200 | | shift.updatedAtTime(), 201 | | 0, // executionFee 202 | | 0 // callbackGasLimit 203 | | ), 204 | | Withdrawal.Flags( 205 | | false 206 | | ) 207 | | ); 208 | | 209 | | cache.withdrawalKey = NonceUtils.getNextKey(params.dataStore); 210 | | params.dataStore.addBytes32( 211 | | Keys.WITHDRAWAL_LIST, 212 | | cache.withdrawalKey 213 | | ); 214 | | WithdrawalEventUtils.emitWithdrawalCreated( 215 | | params.eventEmitter, 216 | | cache.withdrawalKey, 217 | | cache.withdrawal, 218 | | WithdrawalUtils.WithdrawalType.Shift 219 | | ); 220 | | 221 | | cache.executeWithdrawalParams = ExecuteWithdrawalUtils.ExecuteWithdrawalParams( 222 | | params.dataStore, 223 | | params.eventEmitter, 224 | | WithdrawalVault(payable(params.shiftVault)), 225 | | params.oracle, 226 | | cache.withdrawalKey, 227 | | params.keeper, 228 | | params.startingGas, 229 | | ISwapPricingUtils.SwapPricingType.Shift 230 | | ); 231 | | 232 | | ExecuteWithdrawalUtils.executeWithdrawal( 233 | | cache.executeWithdrawalParams, 234 | | cache.withdrawal 235 | | ); 236 | | 237 | | // if the initialLongToken and initialShortToken are the same, only the initialLongTokenAmount would 238 | | // be non-zero, the initialShortTokenAmount would be zero 239 | | cache.initialLongTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.longToken); 240 | | cache.initialShortTokenAmount = params.shiftVault.recordTransferIn(cache.depositMarket.shortToken); 241 | | 242 | | // set the uiFeeReceiver to the zero address since the ui fee was already paid 243 | | // while executing the withdrawal 244 | | cache.deposit = Deposit.Props( 245 | | Deposit.Addresses( 246 | | shift.account(), 247 | | shift.receiver(), 248 | | address(0), // callbackContract 249 | | address(0), // uiFeeReceiver 250 | | shift.toMarket(), // market 251 | | cache.depositMarket.longToken, // initialLongToken 252 | | cache.depositMarket.shortToken, // initialShortToken 253 | | new address[](0), // longTokenSwapPath 254 | | new address[](0) // shortTokenSwapPath 255 | | ), 256 | | Deposit.Numbers( 257 | | cache.initialLongTokenAmount, 258 | | cache.initialShortTokenAmount, 259 | | shift.minMarketTokens(), 260 | | 0, // updatedAtBlock 261 | | shift.updatedAtTime(), 262 | | 0, // executionFee 263 | | 0 // callbackGasLimit 264 | | ), 265 | | Deposit.Flags( 266 | | false // shouldUnwrapNativeToken 267 | | ) 268 | | ); 269 | | 270 | | cache.depositKey = NonceUtils.getNextKey(params.dataStore); 271 | | params.dataStore.addBytes32( 272 | | Keys.DEPOSIT_LIST, 273 | | cache.depositKey 274 | | ); 275 | | DepositEventUtils.emitDepositCreated(params.eventEmitter, cache.depositKey, cache.deposit, DepositUtils.DepositType.Shift); 276 | | 277 | | // price impact from changes in virtual inventory should be excluded 278 | | // since the action of withdrawing and depositing should not result in 279 | | // a net change of virtual inventory 280 | | cache.executeDepositParams = ExecuteDepositUtils.ExecuteDepositParams( 281 | | params.dataStore, 282 | | params.eventEmitter, 283 | | DepositVault(payable(params.shiftVault)), 284 | | params.oracle, 285 | | cache.depositKey, 286 | | params.keeper, 287 | | params.startingGas, 288 | | ISwapPricingUtils.SwapPricingType.Shift, 289 | | false // includeVirtualInventoryImpact 290 | | ); 291 | | 292 | | uint256 receivedMarketTokens = ExecuteDepositUtils.executeDeposit( 293 | | cache.executeDepositParams, 294 | | cache.deposit 295 | | ); 296 | | 297 | | ShiftEventUtils.emitShiftExecuted( 298 | | params.eventEmitter, 299 | | params.key, 300 | | shift.account(), 301 | | receivedMarketTokens 302 | | ); 303 | | 304 | | EventUtils.EventLogData memory eventData; 305 | | eventData.uintItems.initItems(1); 306 | | eventData.uintItems.setItem(0, "receivedMarketTokens", receivedMarketTokens); 307 | | CallbackUtils.afterShiftExecution(params.key, shift, eventData); 308 | | 309 | | GasUtils.payExecutionFee( 310 | | params.dataStore, 311 | | params.eventEmitter, 312 | | params.shiftVault, 313 | | params.key, 314 | | shift.callbackContract(), 315 | | shift.executionFee(), 316 | | params.startingGas, 317 | | GasUtils.estimateShiftOraclePriceCount(), 318 | | params.keeper, 319 | | shift.receiver() 320 | | ); 321 | | } 322 | | 323 | | function cancelShift( 324 | | DataStore dataStore, 325 | | EventEmitter eventEmitter, 326 | | ShiftVault shiftVault, 327 | | bytes32 key, 328 | | address keeper, 329 | | uint256 startingGas, 330 | | string memory reason, 331 | | bytes memory reasonBytes 332 | | ) internal { 333 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 334 | | startingGas -= gasleft() / 63; 335 | | 336 | | Shift.Props memory shift = ShiftStoreUtils.get(dataStore, key); 337 | | 338 | | if (shift.account() == address(0)) { 339 | | revert Errors.EmptyShift(); 340 | | } 341 | | 342 | | if (shift.marketTokenAmount() == 0) { 343 | | revert Errors.EmptyShiftAmount(); 344 | | } 345 | | 346 | | ShiftStoreUtils.remove(dataStore, key, shift.account()); 347 | | 348 | | shiftVault.transferOut( 349 | | shift.fromMarket(), 350 | | shift.account(), 351 | | shift.marketTokenAmount(), 352 | | false // shouldUnwrapNativeToken 353 | | ); 354 | | 355 | | ShiftEventUtils.emitShiftCancelled( 356 | | eventEmitter, 357 | | key, 358 | | shift.account(), 359 | | reason, 360 | | reasonBytes 361 | | ); 362 | | 363 | | EventUtils.EventLogData memory eventData; 364 | | CallbackUtils.afterShiftCancellation(key, shift, eventData); 365 | | 366 | | GasUtils.payExecutionFee( 367 | | dataStore, 368 | | eventEmitter, 369 | | shiftVault, 370 | | key, 371 | | shift.callbackContract(), 372 | | shift.executionFee(), 373 | | startingGas, 374 | | GasUtils.estimateShiftOraclePriceCount(), 375 | | keeper, 376 | | shift.receiver() 377 | | ); 378 | | } 379 | | } 380 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/shift/ShiftVault.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../bank/StrictBank.sol"; 6 | | 7 | * | contract ShiftVault is StrictBank { 8 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {} 9 | | } 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/subaccount/SubaccountUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../event/EventEmitter.sol"; 8 | | import "../utils/Cast.sol"; 9 | | 10 | * | library SubaccountUtils { 11 | | using EventUtils for EventUtils.AddressItems; 12 | | using EventUtils for EventUtils.UintItems; 13 | | using EventUtils for EventUtils.IntItems; 14 | | using EventUtils for EventUtils.BoolItems; 15 | | using EventUtils for EventUtils.Bytes32Items; 16 | | using EventUtils for EventUtils.BytesItems; 17 | | using EventUtils for EventUtils.StringItems; 18 | | 19 | | function addSubaccount( 20 | | DataStore dataStore, 21 | | EventEmitter eventEmitter, 22 | | address account, 23 | | address subaccount 24 | | ) internal { 25 | | bytes32 setKey = Keys.subaccountListKey(account); 26 | | dataStore.addAddress(setKey, subaccount); 27 | | 28 | | EventUtils.EventLogData memory eventData; 29 | | 30 | | eventData.addressItems.initItems(2); 31 | | eventData.addressItems.setItem(0, "account", account); 32 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 33 | | 34 | | eventEmitter.emitEventLog2( 35 | | "AddSubaccount", 36 | | Cast.toBytes32(account), 37 | | Cast.toBytes32(subaccount), 38 | | eventData 39 | | ); 40 | | } 41 | | 42 | | function removeSubaccount( 43 | | DataStore dataStore, 44 | | EventEmitter eventEmitter, 45 | | address account, 46 | | address subaccount 47 | | ) internal { 48 | | bytes32 setKey = Keys.subaccountListKey(account); 49 | | dataStore.removeAddress(setKey, subaccount); 50 | | 51 | | EventUtils.EventLogData memory eventData; 52 | | 53 | | eventData.addressItems.initItems(2); 54 | | eventData.addressItems.setItem(0, "account", account); 55 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 56 | | 57 | | eventEmitter.emitEventLog2( 58 | | "RemoveSubaccount", 59 | | Cast.toBytes32(account), 60 | | Cast.toBytes32(subaccount), 61 | | eventData 62 | | ); 63 | | } 64 | | 65 | | function incrementSubaccountActionCount( 66 | | DataStore dataStore, 67 | | EventEmitter eventEmitter, 68 | | address account, 69 | | address subaccount, 70 | | bytes32 actionType 71 | | ) internal { 72 | | bytes32 key = Keys.subaccountActionCountKey(account, subaccount, actionType); 73 | | uint256 nextValue = dataStore.incrementUint(key, 1); 74 | | validateSubaccountActionCount(dataStore, account, subaccount, actionType, nextValue); 75 | | 76 | | EventUtils.EventLogData memory eventData; 77 | | 78 | | eventData.addressItems.initItems(2); 79 | | eventData.addressItems.setItem(0, "account", account); 80 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 81 | | 82 | | eventData.uintItems.initItems(1); 83 | | eventData.uintItems.setItem(0, "nextValue", nextValue); 84 | | 85 | | eventData.bytes32Items.initItems(1); 86 | | eventData.bytes32Items.setItem(0, "actionType", actionType); 87 | | 88 | | eventEmitter.emitEventLog2( 89 | | "IncrementSubaccountActionCount", 90 | | Cast.toBytes32(account), 91 | | Cast.toBytes32(subaccount), 92 | | eventData 93 | | ); 94 | | } 95 | | 96 | | function setMaxAllowedSubaccountActionCount( 97 | | DataStore dataStore, 98 | | EventEmitter eventEmitter, 99 | | address account, 100 | | address subaccount, 101 | | bytes32 actionType, 102 | | uint256 maxAllowedCount 103 | | ) internal { 104 | | bytes32 key = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType); 105 | | dataStore.setUint(key, maxAllowedCount); 106 | | 107 | | EventUtils.EventLogData memory eventData; 108 | | 109 | | eventData.addressItems.initItems(2); 110 | | eventData.addressItems.setItem(0, "account", account); 111 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 112 | | 113 | | eventData.uintItems.initItems(1); 114 | | eventData.uintItems.setItem(0, "maxAllowedCount", maxAllowedCount); 115 | | 116 | | eventEmitter.emitEventLog2( 117 | | "SetMaxAllowedSubaccountActionCount", 118 | | Cast.toBytes32(account), 119 | | Cast.toBytes32(subaccount), 120 | | eventData 121 | | ); 122 | | } 123 | | 124 | | function validateSubaccountActionCount( 125 | | DataStore dataStore, 126 | | address account, 127 | | address subaccount, 128 | | bytes32 actionType, 129 | | uint256 count 130 | | ) internal view { 131 | | bytes32 key = Keys.maxAllowedSubaccountActionCountKey(account, subaccount, actionType); 132 | | uint256 maxCount = dataStore.getUint(key); 133 | | if (count > maxCount) { 134 | | revert Errors.MaxSubaccountActionCountExceeded(account, subaccount, count, maxCount); 135 | | } 136 | | } 137 | | 138 | | function validateSubaccount( 139 | | DataStore dataStore, 140 | | address account, 141 | | address subaccount 142 | | ) internal view { 143 | | bytes32 setKey = Keys.subaccountListKey(account); 144 | | if (!dataStore.containsAddress(setKey, subaccount)) { 145 | | revert Errors.SubaccountNotAuthorized(account, subaccount); 146 | | } 147 | | } 148 | | 149 | | function getSubaccountAutoTopUpAmount( 150 | | DataStore dataStore, 151 | | address account, 152 | | address subaccount 153 | | ) internal view returns (uint256) { 154 | | bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount); 155 | | return dataStore.getUint(key); 156 | | } 157 | | 158 | | function setSubaccountAutoTopUpAmount( 159 | | DataStore dataStore, 160 | | EventEmitter eventEmitter, 161 | | address account, 162 | | address subaccount, 163 | | uint256 amount 164 | | ) internal { 165 | | bytes32 key = Keys.subaccountAutoTopUpAmountKey(account, subaccount); 166 | | 167 | | dataStore.setUint(key, amount); 168 | | 169 | | EventUtils.EventLogData memory eventData; 170 | | 171 | | eventData.addressItems.initItems(2); 172 | | eventData.addressItems.setItem(0, "account", account); 173 | | eventData.addressItems.setItem(1, "subaccount", subaccount); 174 | | 175 | | eventData.uintItems.initItems(1); 176 | | eventData.uintItems.setItem(0, "amount", amount); 177 | | 178 | | eventEmitter.emitEventLog2( 179 | | "SetSubaccountAutoTopUpAmount", 180 | | Cast.toBytes32(account), 181 | | Cast.toBytes32(subaccount), 182 | | eventData 183 | | ); 184 | | } 185 | | } 186 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/swap/SwapHandler.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 6 | | 7 | | import "../role/RoleModule.sol"; 8 | | import "./SwapUtils.sol"; 9 | | 10 | | /** 11 | | * @title SwapHandler 12 | | * @dev A contract to help with swap functions 13 | | */ 14 | * | contract SwapHandler is ReentrancyGuard, RoleModule { 15 | | constructor(RoleStore _roleStore) RoleModule(_roleStore) {} 16 | | 17 | | /** 18 | | * @dev perform a swap based on the given params 19 | | * @param params SwapUtils.SwapParams 20 | | * @return (outputToken, outputAmount) 21 | | */ 22 | * | function swap( 23 | | SwapUtils.SwapParams memory params 24 | | ) 25 | | external 26 | | nonReentrant 27 | | onlyController 28 | * | returns (address, uint256) 29 | | { 30 | * | return SwapUtils.swap(params); 31 | | } 32 | | } 33 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/swap/SwapUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../adl/AdlUtils.sol"; 6 | | import "../data/DataStore.sol"; 7 | | import "../event/EventEmitter.sol"; 8 | | import "../oracle/Oracle.sol"; 9 | | import "../pricing/SwapPricingUtils.sol"; 10 | | import "../token/TokenUtils.sol"; 11 | | import "../fee/FeeUtils.sol"; 12 | | 13 | | /** 14 | | * @title SwapUtils 15 | | * @dev Library for swap functions 16 | | */ 17 | * | library SwapUtils { 18 | | using SafeCast for uint256; 19 | | using SafeCast for int256; 20 | | using Price for Price.Props; 21 | | 22 | | using EventUtils for EventUtils.AddressItems; 23 | | using EventUtils for EventUtils.UintItems; 24 | | using EventUtils for EventUtils.IntItems; 25 | | using EventUtils for EventUtils.BoolItems; 26 | | using EventUtils for EventUtils.Bytes32Items; 27 | | using EventUtils for EventUtils.BytesItems; 28 | | using EventUtils for EventUtils.StringItems; 29 | | 30 | | /** 31 | | * @param dataStore The contract that provides access to data stored on-chain. 32 | | * @param eventEmitter The contract that emits events. 33 | | * @param oracle The contract that provides access to price data from oracles. 34 | | * @param bank The contract providing the funds for the swap. 35 | | * @param key An identifying key for the swap. 36 | | * @param tokenIn The address of the token that is being swapped. 37 | | * @param amountIn The amount of the token that is being swapped. 38 | | * @param swapPathMarkets An array of market properties, specifying the markets in which the swap should be executed. 39 | | * @param minOutputAmount The minimum amount of tokens that should be received as part of the swap. 40 | | * @param receiver The address to which the swapped tokens should be sent. 41 | | * @param uiFeeReceiver The address of the ui fee receiver. 42 | | * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped. 43 | | */ 44 | | struct SwapParams { 45 | | DataStore dataStore; 46 | | EventEmitter eventEmitter; 47 | | Oracle oracle; 48 | | Bank bank; 49 | | bytes32 key; 50 | | address tokenIn; 51 | | uint256 amountIn; 52 | | Market.Props[] swapPathMarkets; 53 | | uint256 minOutputAmount; 54 | | address receiver; 55 | | address uiFeeReceiver; 56 | | bool shouldUnwrapNativeToken; 57 | | } 58 | | 59 | | /** 60 | | * @param market The market in which the swap should be executed. 61 | | * @param tokenIn The address of the token that is being swapped. 62 | | * @param amountIn The amount of the token that is being swapped. 63 | | * @param receiver The address to which the swapped tokens should be sent. 64 | | * @param shouldUnwrapNativeToken A boolean indicating whether the received tokens should be unwrapped from the wrapped native token (WNT) if they are wrapped. 65 | | */ 66 | | struct _SwapParams { 67 | | Market.Props market; 68 | | address tokenIn; 69 | | uint256 amountIn; 70 | | address receiver; 71 | | bool shouldUnwrapNativeToken; 72 | | } 73 | | 74 | | /** 75 | | * @param tokenOut The address of the token that is being received as part of the swap. 76 | | * @param tokenInPrice The price of the token that is being swapped. 77 | | * @param tokenOutPrice The price of the token that is being received as part of the swap. 78 | | * @param amountIn The amount of the token that is being swapped. 79 | | * @param amountOut The amount of the token that is being received as part of the swap. 80 | | * @param poolAmountOut The total amount of the token that is being received by all users in the swap pool. 81 | | */ 82 | | struct SwapCache { 83 | | address tokenOut; 84 | | Price.Props tokenInPrice; 85 | | Price.Props tokenOutPrice; 86 | | uint256 amountIn; 87 | | uint256 amountInAfterFees; 88 | | uint256 amountOut; 89 | | uint256 poolAmountOut; 90 | | int256 priceImpactUsd; 91 | | int256 priceImpactAmount; 92 | | uint256 cappedDiffUsd; 93 | | int256 tokenInPriceImpactAmount; 94 | | } 95 | | 96 | | event SwapReverted(string reason, bytes reasonBytes); 97 | | 98 | | /** 99 | | * @dev Swaps a given amount of a given token for another token based on a 100 | | * specified swap path. 101 | | * @param params The parameters for the swap. 102 | | * @return A tuple containing the address of the token that was received as 103 | | * part of the swap and the amount of the received token. 104 | | */ 105 | * | function swap(SwapParams memory params) internal returns (address, uint256) { 106 | * | if (params.amountIn == 0) { 107 | * | return (params.tokenIn, params.amountIn); 108 | | } 109 | | 110 | * | if (params.swapPathMarkets.length == 0) { 111 | * | if (params.amountIn < params.minOutputAmount) { 112 | | revert Errors.InsufficientOutputAmount(params.amountIn, params.minOutputAmount); 113 | | } 114 | | 115 | * | if (address(params.bank) != params.receiver) { 116 | * | params.bank.transferOut( 117 | * | params.tokenIn, 118 | * | params.receiver, 119 | * | params.amountIn, 120 | * | params.shouldUnwrapNativeToken 121 | | ); 122 | | } 123 | | 124 | * | return (params.tokenIn, params.amountIn); 125 | | } 126 | | 127 | * | if (address(params.bank) != params.swapPathMarkets[0].marketToken) { 128 | * | params.bank.transferOut( 129 | * | params.tokenIn, 130 | * | params.swapPathMarkets[0].marketToken, 131 | * | params.amountIn, 132 | * | false 133 | | ); 134 | | } 135 | | 136 | * | address tokenOut = params.tokenIn; 137 | * | uint256 outputAmount = params.amountIn; 138 | | 139 | * | for (uint256 i; i < params.swapPathMarkets.length; i++) { 140 | * | Market.Props memory market = params.swapPathMarkets[i]; 141 | | 142 | * | bool flagExists = params.dataStore.getBool(Keys.swapPathMarketFlagKey(market.marketToken)); 143 | * | if (flagExists) { 144 | | revert Errors.DuplicatedMarketInSwapPath(market.marketToken); 145 | | } 146 | | 147 | * | params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), true); 148 | | 149 | * | uint256 nextIndex = i + 1; 150 | * | address receiver; 151 | * | if (nextIndex < params.swapPathMarkets.length) { 152 | * | receiver = params.swapPathMarkets[nextIndex].marketToken; 153 | | } else { 154 | * | receiver = params.receiver; 155 | | } 156 | | 157 | * | _SwapParams memory _params = _SwapParams( 158 | * | market, 159 | * | tokenOut, 160 | * | outputAmount, 161 | * | receiver, 162 | * | i == params.swapPathMarkets.length - 1 ? params.shouldUnwrapNativeToken : false // only convert ETH on the last swap if needed 163 | | ); 164 | | 165 | * | (tokenOut, outputAmount) = _swap(params, _params); 166 | | } 167 | | 168 | * | for (uint256 i; i < params.swapPathMarkets.length; i++) { 169 | * | Market.Props memory market = params.swapPathMarkets[i]; 170 | * | params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), false); 171 | | } 172 | | 173 | * | if (outputAmount < params.minOutputAmount) { 174 | | revert Errors.InsufficientSwapOutputAmount(outputAmount, params.minOutputAmount); 175 | | } 176 | | 177 | * | return (tokenOut, outputAmount); 178 | | } 179 | | 180 | | function validateSwapOutputToken( 181 | | DataStore dataStore, 182 | | address[] memory swapPath, 183 | | address inputToken, 184 | | address expectedOutputToken 185 | | ) internal view { 186 | | address outputToken = getOutputToken(dataStore, swapPath, inputToken); 187 | | if (outputToken != expectedOutputToken) { 188 | | revert Errors.InvalidSwapOutputToken(outputToken, expectedOutputToken); 189 | | } 190 | | } 191 | | 192 | | function getOutputToken( 193 | | DataStore dataStore, 194 | | address[] memory swapPath, 195 | | address inputToken 196 | | ) internal view returns (address) { 197 | | address outputToken = inputToken; 198 | | Market.Props[] memory markets = MarketUtils.getSwapPathMarkets(dataStore, swapPath); 199 | | uint256 marketCount = markets.length; 200 | | 201 | | for (uint256 i; i < marketCount; i++) { 202 | | Market.Props memory market = markets[i]; 203 | | outputToken = MarketUtils.getOppositeToken(outputToken, market); 204 | | } 205 | | 206 | | return outputToken; 207 | | } 208 | | 209 | | /** 210 | | * Performs a swap on a single market. 211 | | * 212 | | * @param params The parameters for the swap. 213 | | * @param _params The parameters for the swap on this specific market. 214 | | * @return The token and amount that was swapped. 215 | | */ 216 | * | function _swap(SwapParams memory params, _SwapParams memory _params) internal returns (address, uint256) { 217 | * | SwapCache memory cache; 218 | | 219 | * | if (_params.tokenIn != _params.market.longToken && _params.tokenIn != _params.market.shortToken) { 220 | * | revert Errors.InvalidTokenIn(_params.tokenIn, _params.market.marketToken); 221 | | } 222 | | 223 | * | MarketUtils.validateSwapMarket(params.dataStore, _params.market); 224 | | 225 | * | cache.tokenOut = MarketUtils.getOppositeToken(_params.tokenIn, _params.market); 226 | * | cache.tokenInPrice = params.oracle.getPrimaryPrice(_params.tokenIn); 227 | * | cache.tokenOutPrice = params.oracle.getPrimaryPrice(cache.tokenOut); 228 | | 229 | | // note that this may not be entirely accurate since the effect of the 230 | | // swap fees are not accounted for 231 | * | cache.priceImpactUsd = SwapPricingUtils.getPriceImpactUsd( 232 | * | SwapPricingUtils.GetPriceImpactUsdParams( 233 | * | params.dataStore, 234 | * | _params.market, 235 | * | _params.tokenIn, 236 | * | cache.tokenOut, 237 | * | cache.tokenInPrice.midPrice(), 238 | * | cache.tokenOutPrice.midPrice(), 239 | * | (_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(), 240 | * | -(_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(), 241 | * | true // includeVirtualInventoryImpact 242 | | ) 243 | | ); 244 | | 245 | * | SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees( 246 | * | params.dataStore, 247 | * | _params.market.marketToken, 248 | * | _params.amountIn, 249 | * | cache.priceImpactUsd > 0, // forPositiveImpact 250 | * | params.uiFeeReceiver, 251 | * | ISwapPricingUtils.SwapPricingType.TwoStep 252 | | ); 253 | | 254 | * | FeeUtils.incrementClaimableFeeAmount( 255 | * | params.dataStore, 256 | * | params.eventEmitter, 257 | * | _params.market.marketToken, 258 | * | _params.tokenIn, 259 | * | fees.feeReceiverAmount, 260 | | Keys.SWAP_FEE_TYPE 261 | | ); 262 | | 263 | * | FeeUtils.incrementClaimableUiFeeAmount( 264 | * | params.dataStore, 265 | * | params.eventEmitter, 266 | * | params.uiFeeReceiver, 267 | * | _params.market.marketToken, 268 | * | _params.tokenIn, 269 | * | fees.uiFeeAmount, 270 | | Keys.UI_SWAP_FEE_TYPE 271 | | ); 272 | | 273 | * | if (cache.priceImpactUsd > 0) { 274 | | // when there is a positive price impact factor, additional tokens from the swap impact pool 275 | | // are withdrawn for the user 276 | | // for example, if 50,000 USDC is swapped out and there is a positive price impact 277 | | // an additional 100 USDC may be sent to the user 278 | | // the swap impact pool is decreased by the used amount 279 | | 280 | | cache.amountIn = fees.amountAfterFees; 281 | | 282 | | (cache.priceImpactAmount, cache.cappedDiffUsd) = MarketUtils.applySwapImpactWithCap( 283 | | params.dataStore, 284 | | params.eventEmitter, 285 | | _params.market.marketToken, 286 | | cache.tokenOut, 287 | | cache.tokenOutPrice, 288 | | cache.priceImpactUsd 289 | | ); 290 | | 291 | | // if the positive price impact was capped, use the tokenIn swap 292 | | // impact pool to pay for the positive price impact 293 | | if (cache.cappedDiffUsd != 0) { 294 | | (cache.tokenInPriceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap( 295 | | params.dataStore, 296 | | params.eventEmitter, 297 | | _params.market.marketToken, 298 | | _params.tokenIn, 299 | | cache.tokenInPrice, 300 | | cache.cappedDiffUsd.toInt256() 301 | | ); 302 | | 303 | | // this additional amountIn is already in the Market 304 | | // it is subtracted from the swap impact pool amount 305 | | // and the market pool amount is increased by the updated 306 | | // amountIn below 307 | | cache.amountIn += cache.tokenInPriceImpactAmount.toUint256(); 308 | | } 309 | | 310 | | // round amountOut down 311 | | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max; 312 | | cache.poolAmountOut = cache.amountOut; 313 | | 314 | | // the below amount is subtracted from the swap impact pool instead of the market pool amount 315 | | cache.amountOut += cache.priceImpactAmount.toUint256(); 316 | | } else { 317 | | // when there is a negative price impact factor, 318 | | // less of the input amount is sent to the pool 319 | | // for example, if 10 ETH is swapped in and there is a negative price impact 320 | | // only 9.995 ETH may be swapped in 321 | | // the remaining 0.005 ETH will be stored in the swap impact pool 322 | | 323 | * | (cache.priceImpactAmount, /* uint256 cappedDiffUsd */) = MarketUtils.applySwapImpactWithCap( 324 | * | params.dataStore, 325 | * | params.eventEmitter, 326 | * | _params.market.marketToken, 327 | * | _params.tokenIn, 328 | * | cache.tokenInPrice, 329 | * | cache.priceImpactUsd 330 | | ); 331 | | 332 | * | if (fees.amountAfterFees <= (-cache.priceImpactAmount).toUint256()) { 333 | | revert Errors.SwapPriceImpactExceedsAmountIn(fees.amountAfterFees, cache.priceImpactAmount); 334 | | } 335 | | 336 | * | cache.amountIn = fees.amountAfterFees - (-cache.priceImpactAmount).toUint256(); 337 | * | cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max; 338 | * | cache.poolAmountOut = cache.amountOut; 339 | | } 340 | | 341 | | // the amountOut value includes the positive price impact amount 342 | * | if (_params.receiver != _params.market.marketToken) { 343 | * | MarketToken(payable(_params.market.marketToken)).transferOut( 344 | * | cache.tokenOut, 345 | * | _params.receiver, 346 | * | cache.amountOut, 347 | * | _params.shouldUnwrapNativeToken 348 | | ); 349 | | } 350 | | 351 | * | MarketUtils.applyDeltaToPoolAmount( 352 | * | params.dataStore, 353 | * | params.eventEmitter, 354 | * | _params.market, 355 | * | _params.tokenIn, 356 | * | (cache.amountIn + fees.feeAmountForPool).toInt256() 357 | | ); 358 | | 359 | | // the poolAmountOut excludes the positive price impact amount 360 | | // as that is deducted from the swap impact pool instead 361 | * | MarketUtils.applyDeltaToPoolAmount( 362 | * | params.dataStore, 363 | * | params.eventEmitter, 364 | * | _params.market, 365 | * | cache.tokenOut, 366 | * | -cache.poolAmountOut.toInt256() 367 | | ); 368 | | 369 | * | MarketUtils.MarketPrices memory prices = MarketUtils.MarketPrices( 370 | * | params.oracle.getPrimaryPrice(_params.market.indexToken), 371 | * | _params.tokenIn == _params.market.longToken ? cache.tokenInPrice : cache.tokenOutPrice, 372 | * | _params.tokenIn == _params.market.shortToken ? cache.tokenInPrice : cache.tokenOutPrice 373 | | ); 374 | | 375 | * | MarketUtils.validatePoolAmount( 376 | * | params.dataStore, 377 | * | _params.market, 378 | * | _params.tokenIn 379 | | ); 380 | | 381 | | // for single token markets cache.tokenOut will always equal _params.market.longToken 382 | | // so only the reserve for longs will be validated 383 | | // swaps should be disabled for single token markets so this should not be an issue 384 | * | MarketUtils.validateReserve( 385 | * | params.dataStore, 386 | * | _params.market, 387 | * | prices, 388 | * | cache.tokenOut == _params.market.longToken 389 | | ); 390 | | 391 | * | MarketUtils.validateMaxPnl( 392 | * | params.dataStore, 393 | * | _params.market, 394 | * | prices, 395 | * | _params.tokenIn == _params.market.longToken ? Keys.MAX_PNL_FACTOR_FOR_DEPOSITS : Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, 396 | * | cache.tokenOut == _params.market.shortToken ? Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS : Keys.MAX_PNL_FACTOR_FOR_DEPOSITS 397 | | ); 398 | | 399 | * | SwapPricingUtils.EmitSwapInfoParams memory emitSwapInfoParams; 400 | | 401 | * | emitSwapInfoParams.orderKey = params.key; 402 | * | emitSwapInfoParams.market = _params.market.marketToken; 403 | * | emitSwapInfoParams.receiver = _params.receiver; 404 | * | emitSwapInfoParams.tokenIn = _params.tokenIn; 405 | * | emitSwapInfoParams.tokenOut = cache.tokenOut; 406 | * | emitSwapInfoParams.tokenInPrice = cache.tokenInPrice.min; 407 | * | emitSwapInfoParams.tokenOutPrice = cache.tokenOutPrice.max; 408 | * | emitSwapInfoParams.amountIn = _params.amountIn; 409 | * | emitSwapInfoParams.amountInAfterFees = fees.amountAfterFees; 410 | * | emitSwapInfoParams.amountOut = cache.amountOut; 411 | * | emitSwapInfoParams.priceImpactUsd = cache.priceImpactUsd; 412 | * | emitSwapInfoParams.priceImpactAmount = cache.priceImpactAmount; 413 | * | emitSwapInfoParams.tokenInPriceImpactAmount = cache.tokenInPriceImpactAmount; 414 | | 415 | * | SwapPricingUtils.emitSwapInfo( 416 | * | params.eventEmitter, 417 | * | emitSwapInfoParams 418 | | ); 419 | | 420 | * | SwapPricingUtils.emitSwapFeesCollected( 421 | * | params.eventEmitter, 422 | * | params.key, 423 | * | _params.market.marketToken, 424 | * | _params.tokenIn, 425 | * | cache.tokenInPrice.min, 426 | | Keys.SWAP_FEE_TYPE, 427 | * | fees 428 | | ); 429 | | 430 | * | return (cache.tokenOut, cache.amountOut); 431 | | } 432 | | } 433 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/ArrayTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../utils/Array.sol"; 7 | | 8 | | /** 9 | | * @title ArrayTest 10 | | * @dev Contract to help test the Array library 11 | | */ 12 | * | contract ArrayTest { 13 | | function getMedian(uint256[] memory arr) internal pure returns (uint256) { 14 | | return Array.getMedian(arr); 15 | | } 16 | | } 17 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/DepositStoreUtilsTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../deposit/DepositStoreUtils.sol"; 7 | | 8 | | /** 9 | | * @title DepositeStoreUtilsTest 10 | | * @dev Contract to help test the DepositStoreUtils library 11 | | */ 12 | * | contract DepositStoreUtilsTest { 13 | | function getEmptyDeposit() internal pure returns (Deposit.Props memory) { 14 | | Deposit.Props memory deposit; 15 | | return deposit; 16 | | } 17 | | 18 | | function setDeposit(DataStore dataStore, bytes32 key, Deposit.Props memory deposit) internal { 19 | | DepositStoreUtils.set(dataStore, key, deposit); 20 | | } 21 | | 22 | | function removeDeposit(DataStore dataStore, bytes32 key, address account) internal { 23 | | DepositStoreUtils.remove(dataStore, key, account); 24 | | } 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/GasUsageTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | /** 7 | | * @title GasUsageTest 8 | | */ 9 | * | contract GasUsageTest { 10 | | function getGasUsageForExternalLibraryCall() internal view returns (uint256, uint256) { 11 | | uint256 startingGas = gasleft(); 12 | | uint256 gasLeft = GasUsageTestLib.getGasLeft(); 13 | | return (startingGas, gasLeft); 14 | | } 15 | | } 16 | | 17 | * | library GasUsageTestLib { 18 | | function getGasLeft() internal view returns (uint256) { 19 | | return gasleft(); 20 | | } 21 | | } 22 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/MarketStoreUtilsTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../market/MarketStoreUtils.sol"; 7 | | 8 | | /** 9 | | * @title MarketStoreUtilsTest 10 | | * @dev Contract to help test the MarketStoreUtils library 11 | | */ 12 | * | contract MarketStoreUtilsTest { 13 | | function getEmptyMarket() internal pure returns (Market.Props memory) { 14 | | Market.Props memory market; 15 | | return market; 16 | | } 17 | | 18 | | function setMarket(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) internal { 19 | | MarketStoreUtils.set(dataStore, key, salt, market); 20 | | } 21 | | 22 | | function removeMarket(DataStore dataStore, address key) internal { 23 | | MarketStoreUtils.remove(dataStore, key); 24 | | } 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/OrderStoreUtilsTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../order/OrderStoreUtils.sol"; 7 | | 8 | | /** 9 | | * @title OrderStoreUtilsTest 10 | | * @dev Contract to help test the OrderStoreUtils library 11 | | */ 12 | * | contract OrderStoreUtilsTest { 13 | | function getEmptyOrder() internal pure returns (Order.Props memory) { 14 | | Order.Props memory order; 15 | | return order; 16 | | } 17 | | 18 | | function setOrder(DataStore dataStore, bytes32 key, Order.Props memory order) internal { 19 | | OrderStoreUtils.set(dataStore, key, order); 20 | | } 21 | | 22 | | function removeOrder(DataStore dataStore, bytes32 key, address account) internal { 23 | | OrderStoreUtils.remove(dataStore, key, account); 24 | | } 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/PositionStoreUtilsTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../position/PositionStoreUtils.sol"; 7 | | 8 | | /** 9 | | * @title PositionStoreUtilsTest 10 | | * @dev Contract to help test the PositionStoreUtils library 11 | | */ 12 | * | contract PositionStoreUtilsTest { 13 | | function getEmptyPosition() internal pure returns (Position.Props memory) { 14 | | Position.Props memory position; 15 | | return position; 16 | | } 17 | | 18 | | function setPosition(DataStore dataStore, bytes32 key, Position.Props memory position) internal { 19 | | PositionStoreUtils.set(dataStore, key, position); 20 | | } 21 | | 22 | | function removePosition(DataStore dataStore, bytes32 key, address account) internal { 23 | | PositionStoreUtils.remove(dataStore, key, account); 24 | | } 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/PricingUtilsTest.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../pricing/PricingUtils.sol"; 6 | | 7 | | /** 8 | | * @title PricingUtilsTest 9 | | * @dev Contract to help test the PricingUtils library 10 | | */ 11 | * | contract PricingUtilsTest { 12 | | function applyImpactFactor( 13 | | uint256 diffUsd, 14 | | uint256 impactFactor, 15 | | uint256 impactExponentFactor 16 | | ) internal pure returns (uint256) { 17 | | return PricingUtils.applyImpactFactor(diffUsd, impactFactor, impactExponentFactor); 18 | | } 19 | | } 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/test/WithdrawalStoreUtilsTest.sol 1 | | 2 | | // SPDX-License-Identifier: BUSL-1.1 3 | | 4 | | pragma solidity ^0.8.0; 5 | | 6 | | import "../withdrawal/WithdrawalStoreUtils.sol"; 7 | | 8 | | /** 9 | | * @title WithdrawalStoreUtilsTest 10 | | * @dev Contract to help test the WithdrawalStoreUtils library 11 | | */ 12 | * | contract WithdrawalStoreUtilsTest { 13 | | function getEmptyWithdrawal() internal pure returns (Withdrawal.Props memory) { 14 | | Withdrawal.Props memory withdrawal; 15 | | return withdrawal; 16 | | } 17 | | 18 | | function setWithdrawal(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) internal { 19 | | WithdrawalStoreUtils.set(dataStore, key, withdrawal); 20 | | } 21 | | 22 | | function removeWithdrawal(DataStore dataStore, bytes32 key, address account) internal { 23 | | WithdrawalStoreUtils.remove(dataStore, key, account); 24 | | } 25 | | } 26 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/token/IWNT.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @title IWNT 7 | | * @dev Interface for Wrapped Native Tokens, e.g. WETH 8 | | * The contract is named WNT instead of WETH for a more general reference name 9 | | * that can be used on any blockchain 10 | | */ 11 | | interface IWNT { 12 | | function deposit() external payable; 13 | | function withdraw(uint256 amount) external; 14 | | } 15 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/token/TokenUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/Address.sol"; 6 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 7 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 8 | | 9 | | import "../data/DataStore.sol"; 10 | | import "../data/Keys.sol"; 11 | | import "../error/ErrorUtils.sol"; 12 | | import "../utils/AccountUtils.sol"; 13 | | 14 | | import "./IWNT.sol"; 15 | | 16 | | /** 17 | | * @title TokenUtils 18 | | * @dev Library for token functions, helps with transferring of tokens and 19 | | * native token functions 20 | | */ 21 | * | library TokenUtils { 22 | | using Address for address; 23 | | using SafeERC20 for IERC20; 24 | | 25 | | event TokenTransferReverted(string reason, bytes returndata); 26 | | event NativeTokenTransferReverted(string reason); 27 | | 28 | | /** 29 | | * @dev Returns the address of the WNT token. 30 | | * @param dataStore DataStore contract instance where the address of the WNT token is stored. 31 | | * @return The address of the WNT token. 32 | | */ 33 | * | function wnt(DataStore dataStore) internal view returns (address) { 34 | * | return dataStore.getAddress(Keys.WNT); 35 | | } 36 | | 37 | | /** 38 | | * @dev Transfers the specified amount of `token` from the caller to `receiver`. 39 | | * limit the amount of gas forwarded so that a user cannot intentionally 40 | | * construct a token call that would consume all gas and prevent necessary 41 | | * actions like request cancellation from being executed 42 | | * 43 | | * @param dataStore The data store that contains the `tokenTransferGasLimit` for the specified `token`. 44 | | * @param token The address of the ERC20 token that is being transferred. 45 | | * @param receiver The address of the recipient of the `token` transfer. 46 | | * @param amount The amount of `token` to transfer. 47 | | */ 48 | * | function transfer( 49 | | DataStore dataStore, 50 | | address token, 51 | | address receiver, 52 | | uint256 amount 53 | | ) internal { 54 | * | if (amount == 0) { return; } 55 | * | AccountUtils.validateReceiver(receiver); 56 | | 57 | * | uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token)); 58 | * | if (gasLimit == 0) { 59 | | revert Errors.EmptyTokenTranferGasLimit(token); 60 | | } 61 | | 62 | * | (bool success0, /* bytes memory returndata */) = nonRevertingTransferWithGasLimit( 63 | * | IERC20(token), 64 | * | receiver, 65 | * | amount, 66 | * | gasLimit 67 | | ); 68 | | 69 | * | if (success0) { return; } 70 | | 71 | | address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS); 72 | | 73 | | if (holdingAddress == address(0)) { 74 | | revert Errors.EmptyHoldingAddress(); 75 | | } 76 | | 77 | | // in case transfers to the receiver fail due to blacklisting or other reasons 78 | | // send the tokens to a holding address to avoid possible gaming through reverting 79 | | // transfers 80 | | (bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit( 81 | | IERC20(token), 82 | | holdingAddress, 83 | | amount, 84 | | gasLimit 85 | | ); 86 | | 87 | | if (success1) { return; } 88 | | 89 | | (string memory reason, /* bool hasRevertMessage */) = ErrorUtils.getRevertMessage(returndata); 90 | | emit TokenTransferReverted(reason, returndata); 91 | | 92 | | // throw custom errors to prevent spoofing of errors 93 | | // this is necessary because contracts like DepositHandler, WithdrawalHandler, OrderHandler 94 | | // do not cancel requests for specific errors 95 | | revert Errors.TokenTransferError(token, receiver, amount); 96 | | } 97 | | 98 | | function sendNativeToken( 99 | | DataStore dataStore, 100 | | address receiver, 101 | | uint256 amount 102 | | ) internal { 103 | | if (amount == 0) { return; } 104 | | 105 | | AccountUtils.validateReceiver(receiver); 106 | | 107 | | uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT); 108 | | 109 | | bool success; 110 | | // use an assembly call to avoid loading large data into memory 111 | | // input mem[in…(in+insize)] 112 | | // output area mem[out…(out+outsize))] 113 | | assembly { 114 | | success := call( 115 | | gasLimit, // gas limit 116 | | receiver, // receiver 117 | | amount, // value 118 | | 0, // in 119 | | 0, // insize 120 | | 0, // out 121 | | 0 // outsize 122 | | ) 123 | | } 124 | | 125 | | if (success) { return; } 126 | | 127 | | // if the transfer failed, re-wrap the token and send it to the receiver 128 | | depositAndSendWrappedNativeToken( 129 | | dataStore, 130 | | receiver, 131 | | amount 132 | | ); 133 | | } 134 | | 135 | | /** 136 | | * Deposits the specified amount of native token and sends the specified 137 | | * amount of wrapped native token to the specified receiver address. 138 | | * 139 | | * @param dataStore the data store to use for storing and retrieving data 140 | | * @param receiver the address of the recipient of the wrapped native token transfer 141 | | * @param amount the amount of native token to deposit and the amount of wrapped native token to send 142 | | */ 143 | * | function depositAndSendWrappedNativeToken( 144 | | DataStore dataStore, 145 | | address receiver, 146 | | uint256 amount 147 | * | ) internal { 148 | * | if (amount == 0) { return; } 149 | * | AccountUtils.validateReceiver(receiver); 150 | | 151 | * | address _wnt = wnt(dataStore); 152 | * | IWNT(_wnt).deposit{value: amount}(); 153 | | 154 | * | transfer( 155 | * | dataStore, 156 | * | _wnt, 157 | * | receiver, 158 | * | amount 159 | | ); 160 | | } 161 | | 162 | | /** 163 | | * @dev Withdraws the specified amount of wrapped native token and sends the 164 | | * corresponding amount of native token to the specified receiver address. 165 | | * 166 | | * limit the amount of gas forwarded so that a user cannot intentionally 167 | | * construct a token call that would consume all gas and prevent necessary 168 | | * actions like request cancellation from being executed 169 | | * 170 | | * @param dataStore the data store to use for storing and retrieving data 171 | | * @param _wnt the address of the WNT contract to withdraw the wrapped native token from 172 | | * @param receiver the address of the recipient of the native token transfer 173 | | * @param amount the amount of wrapped native token to withdraw and the amount of native token to send 174 | | */ 175 | | function withdrawAndSendNativeToken( 176 | | DataStore dataStore, 177 | | address _wnt, 178 | | address receiver, 179 | | uint256 amount 180 | | ) internal { 181 | | if (amount == 0) { return; } 182 | | AccountUtils.validateReceiver(receiver); 183 | | 184 | | IWNT(_wnt).withdraw(amount); 185 | | 186 | | uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT); 187 | | 188 | | bool success; 189 | | // use an assembly call to avoid loading large data into memory 190 | | // input mem[in…(in+insize)] 191 | | // output area mem[out…(out+outsize))] 192 | | assembly { 193 | | success := call( 194 | | gasLimit, // gas limit 195 | | receiver, // receiver 196 | | amount, // value 197 | | 0, // in 198 | | 0, // insize 199 | | 0, // out 200 | | 0 // outsize 201 | | ) 202 | | } 203 | | 204 | | if (success) { return; } 205 | | 206 | | // if the transfer failed, re-wrap the token and send it to the receiver 207 | | depositAndSendWrappedNativeToken( 208 | | dataStore, 209 | | receiver, 210 | | amount 211 | | ); 212 | | } 213 | | 214 | | /** 215 | | * @dev Transfers the specified amount of ERC20 token to the specified receiver 216 | | * address, with a gas limit to prevent the transfer from consuming all available gas. 217 | | * adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/utils/SafeERC20.sol 218 | | * 219 | | * @param token the ERC20 contract to transfer the tokens from 220 | | * @param to the address of the recipient of the token transfer 221 | | * @param amount the amount of tokens to transfer 222 | | * @param gasLimit the maximum amount of gas that the token transfer can consume 223 | | * @return a tuple containing a boolean indicating the success or failure of the 224 | | * token transfer, and a bytes value containing the return data from the token transfer 225 | | */ 226 | * | function nonRevertingTransferWithGasLimit( 227 | | IERC20 token, 228 | | address to, 229 | | uint256 amount, 230 | | uint256 gasLimit 231 | * | ) internal returns (bool, bytes memory) { 232 | * | bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount); 233 | * | (bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data); 234 | | 235 | * | if (success) { 236 | * | if (returndata.length == 0) { 237 | | // only check isContract if the call was successful and the return data is empty 238 | | // otherwise we already know that it was a contract 239 | | if (!address(token).isContract()) { 240 | | return (false, "Call to non-contract"); 241 | | } 242 | | } 243 | | 244 | | // some tokens do not revert on a failed transfer, they will return a boolean instead 245 | | // validate that the returned boolean is true, otherwise indicate that the token transfer failed 246 | * | if (returndata.length > 0 && !abi.decode(returndata, (bool))) { 247 | | return (false, returndata); 248 | | } 249 | | 250 | | // transfers on some tokens do not return a boolean value, they will just revert if a transfer fails 251 | | // for these tokens, if success is true then the transfer should have completed 252 | * | return (true, returndata); 253 | | } 254 | | 255 | | return (false, returndata); 256 | | } 257 | | } 258 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/AccountUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../error/Errors.sol"; 6 | | 7 | * | library AccountUtils { 8 | * | function validateAccount(address account) internal pure { 9 | * | if (account == address(0)) { 10 | | revert Errors.EmptyAccount(); 11 | | } 12 | | } 13 | | 14 | * | function validateReceiver(address receiver) internal pure { 15 | * | if (receiver == address(0)) { 16 | | revert Errors.EmptyReceiver(); 17 | | } 18 | | } 19 | | } 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Array.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 6 | | import "../error/Errors.sol"; 7 | | 8 | | /** 9 | | * @title Array 10 | | * @dev Library for array functions 11 | | */ 12 | * | library Array { 13 | | using SafeCast for int256; 14 | | 15 | | /** 16 | | * @dev Gets the value of the element at the specified index in the given array. If the index is out of bounds, returns 0. 17 | | * 18 | | * @param arr the array to get the value from 19 | | * @param index the index of the element in the array 20 | | * @return the value of the element at the specified index in the array 21 | | */ 22 | | function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) { 23 | | if (index < arr.length) { 24 | | return arr[index]; 25 | | } 26 | | 27 | | return bytes32(0); 28 | | } 29 | | 30 | | /** 31 | | * @dev Determines whether all of the elements in the given array are equal to the specified value. 32 | | * 33 | | * @param arr the array to check the elements of 34 | | * @param value the value to compare the elements of the array to 35 | | * @return true if all of the elements in the array are equal to the specified value, false otherwise 36 | | */ 37 | | function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) { 38 | | for (uint256 i; i < arr.length; i++) { 39 | | if (arr[i] != value) { 40 | | return false; 41 | | } 42 | | } 43 | | 44 | | return true; 45 | | } 46 | | 47 | | /** 48 | | * @dev Determines whether all of the elements in the given array are greater than the specified value. 49 | | * 50 | | * @param arr the array to check the elements of 51 | | * @param value the value to compare the elements of the array to 52 | | * @return true if all of the elements in the array are greater than the specified value, false otherwise 53 | | */ 54 | | function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) { 55 | | for (uint256 i; i < arr.length; i++) { 56 | | if (arr[i] <= value) { 57 | | return false; 58 | | } 59 | | } 60 | | 61 | | return true; 62 | | } 63 | | 64 | | /** 65 | | * @dev Determines whether all of the elements in the given array are greater than or equal to the specified value. 66 | | * 67 | | * @param arr the array to check the elements of 68 | | * @param value the value to compare the elements of the array to 69 | | * @return true if all of the elements in the array are greater than or equal to the specified value, false otherwise 70 | | */ 71 | | function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) { 72 | | for (uint256 i; i < arr.length; i++) { 73 | | if (arr[i] < value) { 74 | | return false; 75 | | } 76 | | } 77 | | 78 | | return true; 79 | | } 80 | | 81 | | /** 82 | | * @dev Determines whether all of the elements in the given array are less than the specified value. 83 | | * 84 | | * @param arr the array to check the elements of 85 | | * @param value the value to compare the elements of the array to 86 | | * @return true if all of the elements in the array are less than the specified value, false otherwise 87 | | */ 88 | | function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) { 89 | | for (uint256 i; i < arr.length; i++) { 90 | | if (arr[i] >= value) { 91 | | return false; 92 | | } 93 | | } 94 | | 95 | | return true; 96 | | } 97 | | 98 | | /** 99 | | * @dev Determines whether all of the elements in the given array are less than or equal to the specified value. 100 | | * 101 | | * @param arr the array to check the elements of 102 | | * @param value the value to compare the elements of the array to 103 | | * @return true if all of the elements in the array are less than or equal to the specified value, false otherwise 104 | | */ 105 | | function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) { 106 | | for (uint256 i; i < arr.length; i++) { 107 | | if (arr[i] > value) { 108 | | return false; 109 | | } 110 | | } 111 | | 112 | | return true; 113 | | } 114 | | 115 | | /** 116 | | * @dev Gets the median value of the elements in the given array. For arrays with an odd number of elements, returns the element at the middle index. For arrays with an even number of elements, returns the average of the two middle elements. 117 | | * 118 | | * @param arr the array to get the median value from 119 | | * @return the median value of the elements in the given array 120 | | */ 121 | | function getMedian(uint256[] memory arr) internal pure returns (uint256) { 122 | | if (arr.length % 2 == 1) { 123 | | return arr[arr.length / 2]; 124 | | } 125 | | 126 | | return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2; 127 | | } 128 | | 129 | | /** 130 | | * @dev Gets the uncompacted value at the specified index in the given array of compacted values. 131 | | * 132 | | * @param compactedValues the array of compacted values to get the uncompacted value from 133 | | * @param index the index of the uncompacted value in the array 134 | | * @param compactedValueBitLength the length of each compacted value, in bits 135 | | * @param bitmask the bitmask to use to extract the uncompacted value from the compacted value 136 | | * @return the uncompacted value at the specified index in the array of compacted values 137 | | */ 138 | | function getUncompactedValue( 139 | | uint256[] memory compactedValues, 140 | | uint256 index, 141 | | uint256 compactedValueBitLength, 142 | | uint256 bitmask, 143 | | string memory label 144 | | ) internal pure returns (uint256) { 145 | | uint256 compactedValuesPerSlot = 256 / compactedValueBitLength; 146 | | 147 | | uint256 slotIndex = index / compactedValuesPerSlot; 148 | | if (slotIndex >= compactedValues.length) { 149 | | revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label); 150 | | } 151 | | 152 | | uint256 slotBits = compactedValues[slotIndex]; 153 | | uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength; 154 | | 155 | | uint256 value = (slotBits >> offset) & bitmask; 156 | | 157 | | return value; 158 | | } 159 | | } 160 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/BasicMulticall.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../error/ErrorUtils.sol"; 6 | | 7 | | /** 8 | | * @title BasicMulticall 9 | | */ 10 | | abstract contract BasicMulticall { 11 | | /** 12 | | * @dev Receives and executes a batch of function calls on this contract. 13 | | */ 14 | | function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { 15 | | results = new bytes[](data.length); 16 | | 17 | | for (uint256 i; i < data.length; i++) { 18 | | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 19 | | 20 | | if (!success) { 21 | | ErrorUtils.revertWithParsedMessage(result); 22 | | } 23 | | 24 | | results[i] = result; 25 | | } 26 | | 27 | | return results; 28 | | } 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Bits.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @title Bits 7 | | * @dev Library for bit values 8 | | */ 9 | * | library Bits { 10 | | // @dev uint256(~0) is 256 bits of 1s 11 | | // @dev shift the 1s by (256 - 8) to get (256 - 8) 0s followed by 8 1s 12 | | uint256 constant internal BITMASK_8 = ~uint256(0) >> (256 - 8); 13 | | // @dev shift the 1s by (256 - 16) to get (256 - 16) 0s followed by 16 1s 14 | | uint256 constant internal BITMASK_16 = ~uint256(0) >> (256 - 16); 15 | | // @dev shift the 1s by (256 - 32) to get (256 - 32) 0s followed by 32 1s 16 | | uint256 constant internal BITMASK_32 = ~uint256(0) >> (256 - 32); 17 | | // @dev shift the 1s by (256 - 64) to get (256 - 64) 0s followed by 64 1s 18 | | uint256 constant internal BITMASK_64 = ~uint256(0) >> (256 - 64); 19 | | } 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Calc.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 6 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 7 | | 8 | | /** 9 | | * @title Calc 10 | | * @dev Library for math functions 11 | | */ 12 | * | library Calc { 13 | | using SignedMath for int256; 14 | | using SafeCast for uint256; 15 | | 16 | | // this method assumes that min is less than max 17 | | function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) { 18 | | uint256 magnitude = value.abs(); 19 | | 20 | | if (magnitude < min) { 21 | | magnitude = min; 22 | | } 23 | | 24 | | if (magnitude > max) { 25 | | magnitude = max; 26 | | } 27 | | 28 | | int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256(); 29 | | 30 | | return magnitude.toInt256() * sign; 31 | | } 32 | | 33 | | /** 34 | | * @dev Calculates the result of dividing the first number by the second number, 35 | | * rounded up to the nearest integer. 36 | | * 37 | | * @param a the dividend 38 | | * @param b the divisor 39 | | * @return the result of dividing the first number by the second number, rounded up to the nearest integer 40 | | */ 41 | * | function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) { 42 | * | return (a + b - 1) / b; 43 | | } 44 | | 45 | | /** 46 | | * Calculates the result of dividing the first number by the second number, 47 | | * rounded up to the nearest integer. 48 | | * The rounding is purely on the magnitude of a, if a is negative the result 49 | | * is a larger magnitude negative 50 | | * 51 | | * @param a the dividend 52 | | * @param b the divisor 53 | | * @return the result of dividing the first number by the second number, rounded up to the nearest integer 54 | | */ 55 | * | function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) { 56 | * | if (a < 0) { 57 | * | return (a - b.toInt256() + 1) / b.toInt256(); 58 | | } 59 | | 60 | * | return (a + b.toInt256() - 1) / b.toInt256(); 61 | | } 62 | | 63 | | /** 64 | | * Adds two numbers together and return a uint256 value, treating the second number as a signed integer. 65 | | * 66 | | * @param a the first number 67 | | * @param b the second number 68 | | * @return the result of adding the two numbers together 69 | | */ 70 | * | function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) { 71 | * | if (b > 0) { 72 | * | return a + b.abs(); 73 | | } 74 | | 75 | * | return a - b.abs(); 76 | | } 77 | | 78 | | /** 79 | | * Adds two numbers together and return an int256 value, treating the second number as a signed integer. 80 | | * 81 | | * @param a the first number 82 | | * @param b the second number 83 | | * @return the result of adding the two numbers together 84 | | */ 85 | | function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) { 86 | | return a.toInt256() + b; 87 | | } 88 | | 89 | | /** 90 | | * @dev Calculates the absolute difference between two numbers. 91 | | * 92 | | * @param a the first number 93 | | * @param b the second number 94 | | * @return the absolute difference between the two numbers 95 | | */ 96 | * | function diff(uint256 a, uint256 b) internal pure returns (uint256) { 97 | * | return a > b ? a - b : b - a; 98 | | } 99 | | 100 | | /** 101 | | * Adds two numbers together, the result is bounded to prevent overflows. 102 | | * 103 | | * @param a the first number 104 | | * @param b the second number 105 | | * @return the result of adding the two numbers together 106 | | */ 107 | | function boundedAdd(int256 a, int256 b) internal pure returns (int256) { 108 | | // if either a or b is zero or if the signs are different there should not be any overflows 109 | | if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) { 110 | | return a + b; 111 | | } 112 | | 113 | | // if adding `b` to `a` would result in a value less than the min int256 value 114 | | // then return the min int256 value 115 | | if (a < 0 && b <= type(int256).min - a) { 116 | | return type(int256).min; 117 | | } 118 | | 119 | | // if adding `b` to `a` would result in a value more than the max int256 value 120 | | // then return the max int256 value 121 | | if (a > 0 && b >= type(int256).max - a) { 122 | | return type(int256).max; 123 | | } 124 | | 125 | | return a + b; 126 | | } 127 | | 128 | | /** 129 | | * Returns a - b, the result is bounded to prevent overflows. 130 | | * Note that this will revert if b is type(int256).min because of the usage of "-b". 131 | | * 132 | | * @param a the first number 133 | | * @param b the second number 134 | | * @return the bounded result of a - b 135 | | */ 136 | | function boundedSub(int256 a, int256 b) internal pure returns (int256) { 137 | | // if either a or b is zero or the signs are the same there should not be any overflow 138 | | if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) { 139 | | return a - b; 140 | | } 141 | | 142 | | // if adding `-b` to `a` would result in a value greater than the max int256 value 143 | | // then return the max int256 value 144 | | if (a > 0 && -b >= type(int256).max - a) { 145 | | return type(int256).max; 146 | | } 147 | | 148 | | // if subtracting `b` from `a` would result in a value less than the min int256 value 149 | | // then return the min int256 value 150 | | if (a < 0 && -b <= type(int256).min - a) { 151 | | return type(int256).min; 152 | | } 153 | | 154 | | return a - b; 155 | | } 156 | | 157 | | 158 | | /** 159 | | * Converts the given unsigned integer to a signed integer, using the given 160 | | * flag to determine whether the result should be positive or negative. 161 | | * 162 | | * @param a the unsigned integer to convert 163 | | * @param isPositive whether the result should be positive (if true) or negative (if false) 164 | | * @return the signed integer representation of the given unsigned integer 165 | | */ 166 | * | function toSigned(uint256 a, bool isPositive) internal pure returns (int256) { 167 | * | if (isPositive) { 168 | * | return a.toInt256(); 169 | | } else { 170 | * | return -a.toInt256(); 171 | | } 172 | | } 173 | | } 174 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Cast.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @title Cast 7 | | * @dev Library for casting functions 8 | | */ 9 | * | library Cast { 10 | * | function toBytes32(address value) internal pure returns (bytes32) { 11 | * | return bytes32(uint256(uint160(value))); 12 | | } 13 | | } 14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/EnumerableValues.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 6 | | 7 | | /** 8 | | * @title EnumerableValues 9 | | * @dev Library to extend the EnumerableSet library with functions to get 10 | | * valuesAt for a range 11 | | */ 12 | * | library EnumerableValues { 13 | | using EnumerableSet for EnumerableSet.Bytes32Set; 14 | | using EnumerableSet for EnumerableSet.AddressSet; 15 | | using EnumerableSet for EnumerableSet.UintSet; 16 | | 17 | | /** 18 | | * Returns an array of bytes32 values from the given set, starting at the given 19 | | * start index and ending before the given end index. 20 | | * 21 | | * @param set The set to get the values from. 22 | | * @param start The starting index. 23 | | * @param end The ending index. 24 | | * @return An array of bytes32 values. 25 | | */ 26 | * | function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 27 | * | uint256 max = set.length(); 28 | * | if (end > max) { end = max; } 29 | | 30 | * | bytes32[] memory items = new bytes32[](end - start); 31 | * | for (uint256 i = start; i < end; i++) { 32 | * | items[i - start] = set.at(i); 33 | | } 34 | | 35 | * | return items; 36 | | } 37 | | 38 | | 39 | | /** 40 | | * Returns an array of address values from the given set, starting at the given 41 | | * start index and ending before the given end index. 42 | | * 43 | | * @param set The set to get the values from. 44 | | * @param start The starting index. 45 | | * @param end The ending index. 46 | | * @return An array of address values. 47 | | */ 48 | | function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) { 49 | | uint256 max = set.length(); 50 | | if (end > max) { end = max; } 51 | | 52 | | address[] memory items = new address[](end - start); 53 | | for (uint256 i = start; i < end; i++) { 54 | | items[i - start] = set.at(i); 55 | | } 56 | | 57 | | return items; 58 | | } 59 | | 60 | | 61 | | /** 62 | | * Returns an array of uint256 values from the given set, starting at the given 63 | | * start index and ending before the given end index, the item at the end index will not be returned. 64 | | * 65 | | * @param set The set to get the values from. 66 | | * @param start The starting index (inclusive, item at the start index will be returned). 67 | | * @param end The ending index (exclusive, item at the end index will not be returned). 68 | | * @return An array of uint256 values. 69 | | */ 70 | | function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) { 71 | | if (start >= set.length()) { 72 | | return new uint256[](0); 73 | | } 74 | | 75 | | uint256 max = set.length(); 76 | | if (end > max) { end = max; } 77 | | 78 | | uint256[] memory items = new uint256[](end - start); 79 | | for (uint256 i = start; i < end; i++) { 80 | | items[i - start] = set.at(i); 81 | | } 82 | | 83 | | return items; 84 | | } 85 | | } 86 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/GlobalReentrancyGuard.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | abstract contract GlobalReentrancyGuard { 9 | | // Booleans are more expensive than uint256 or any type that takes up a full 10 | | // word because each write operation emits an extra SLOAD to first read the 11 | | // slot's contents, replace the bits taken up by the boolean, and then write 12 | | // back. This is the compiler's defense against contract upgrades and 13 | | // pointer aliasing, and it cannot be disabled. 14 | * | uint256 private constant NOT_ENTERED = 0; 15 | * | uint256 private constant ENTERED = 1; 16 | | 17 | | DataStore public immutable dataStore; 18 | | 19 | | constructor(DataStore _dataStore) { 20 | | dataStore = _dataStore; 21 | | } 22 | | 23 | | modifier globalNonReentrant() { 24 | * | _globalNonReentrantBefore(); 25 | | _; 26 | * | _globalNonReentrantAfter(); 27 | | } 28 | | 29 | * | function _globalNonReentrantBefore() private { 30 | * | uint256 status = dataStore.getUint(Keys.REENTRANCY_GUARD_STATUS); 31 | | 32 | * | require(status == NOT_ENTERED, "ReentrancyGuard: reentrant call"); 33 | | 34 | * | dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, ENTERED); 35 | | } 36 | | 37 | * | function _globalNonReentrantAfter() private { 38 | * | dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, NOT_ENTERED); 39 | | } 40 | | } 41 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/PayableMulticall.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../error/ErrorUtils.sol"; 6 | | 7 | | /** 8 | | * @title PayableMulticall 9 | | * @dev Contract to help call multiple functions in a single transaction 10 | | * all function calls will have the original sender as the msg.sender value 11 | | * IMPORTANT: in the multicall, msg.value will be the same for each delegatecall 12 | | * extra care should be taken if msg.value is used in any of the functions of the inheriting contract 13 | | */ 14 | | abstract contract PayableMulticall { 15 | | /** 16 | | * @dev Receives and executes a batch of function calls on this contract. 17 | | */ 18 | | function multicall(bytes[] calldata data) external payable virtual returns (bytes[] memory results) { 19 | | results = new bytes[](data.length); 20 | | 21 | | for (uint256 i; i < data.length; i++) { 22 | | (bool success, bytes memory result) = address(this).delegatecall(data[i]); 23 | | 24 | | if (!success) { 25 | | ErrorUtils.revertWithParsedMessage(result); 26 | | } 27 | | 28 | | results[i] = result; 29 | | } 30 | | 31 | | return results; 32 | | } 33 | | } 34 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Precision.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | // there is a known issue with prb-math v3.x releases 6 | | // https://github.com/PaulRBerg/prb-math/issues/178 7 | | // due to this, either prb-math v2.x or v4.x versions should be used instead 8 | | import "prb-math/contracts/PRBMathUD60x18.sol"; 9 | | 10 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 11 | | import "@openzeppelin/contracts/utils/math/SafeMath.sol"; 12 | | import "@openzeppelin/contracts/utils/math/SignedMath.sol"; 13 | | import "@openzeppelin/contracts/utils/math/Math.sol"; 14 | | 15 | | import "./Calc.sol"; 16 | | 17 | | /** 18 | | * @title Precision 19 | | * @dev Library for precision values and conversions 20 | | */ 21 | * | library Precision { 22 | | using SafeCast for uint256; 23 | | using SignedMath for int256; 24 | | 25 | * | uint256 internal constant FLOAT_PRECISION = 10 ** 30; 26 | * | uint256 internal constant FLOAT_PRECISION_SQRT = 10 ** 15; 27 | | 28 | | uint256 internal constant WEI_PRECISION = 10 ** 18; 29 | * | uint256 internal constant BASIS_POINTS_DIVISOR = 10000; 30 | | 31 | * | uint256 internal constant FLOAT_TO_WEI_DIVISOR = 10 ** 12; 32 | | 33 | | /** 34 | | * Applies the given factor to the given value and returns the result. 35 | | * 36 | | * @param value The value to apply the factor to. 37 | | * @param factor The factor to apply. 38 | | * @return The result of applying the factor to the value. 39 | | */ 40 | * | function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) { 41 | * | return mulDiv(value, factor, FLOAT_PRECISION); 42 | | } 43 | | 44 | | /** 45 | | * Applies the given factor to the given value and returns the result. 46 | | * 47 | | * @param value The value to apply the factor to. 48 | | * @param factor The factor to apply. 49 | | * @return The result of applying the factor to the value. 50 | | */ 51 | | function applyFactor(uint256 value, int256 factor) internal pure returns (int256) { 52 | | return mulDiv(value, factor, FLOAT_PRECISION); 53 | | } 54 | | 55 | | function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) { 56 | | return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude); 57 | | } 58 | | 59 | * | function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) { 60 | * | return Math.mulDiv(value, numerator, denominator); 61 | | } 62 | | 63 | * | function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) { 64 | * | return mulDiv(numerator, value, denominator); 65 | | } 66 | | 67 | * | function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) { 68 | * | uint256 result = mulDiv(value, numerator.abs(), denominator); 69 | * | return numerator > 0 ? result.toInt256() : -result.toInt256(); 70 | | } 71 | | 72 | | function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) { 73 | | uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude); 74 | | return numerator > 0 ? result.toInt256() : -result.toInt256(); 75 | | } 76 | | 77 | * | function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) { 78 | * | if (roundUpMagnitude) { 79 | * | return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up); 80 | | } 81 | | 82 | * | return Math.mulDiv(value, numerator, denominator); 83 | | } 84 | | 85 | * | function applyExponentFactor( 86 | | uint256 floatValue, 87 | | uint256 exponentFactor 88 | * | ) internal pure returns (uint256) { 89 | | // `PRBMathUD60x18.pow` doesn't work for `x` less than one 90 | * | if (floatValue < FLOAT_PRECISION) { 91 | * | return 0; 92 | | } 93 | | 94 | * | if (exponentFactor == FLOAT_PRECISION) { 95 | * | return floatValue; 96 | | } 97 | | 98 | | // `PRBMathUD60x18.pow` accepts 2 fixed point numbers 60x18 99 | | // we need to convert float (30 decimals) to 60x18 (18 decimals) and then back to 30 decimals 100 | * | uint256 weiValue = PRBMathUD60x18.pow( 101 | * | floatToWei(floatValue), 102 | * | floatToWei(exponentFactor) 103 | | ); 104 | | 105 | * | return weiToFloat(weiValue); 106 | | } 107 | | 108 | * | function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) { 109 | * | if (value == 0) { return 0; } 110 | | 111 | * | if (roundUpMagnitude) { 112 | | return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up); 113 | | } 114 | | 115 | * | return Math.mulDiv(value, FLOAT_PRECISION, divisor); 116 | | } 117 | | 118 | * | function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) { 119 | * | return toFactor(value, divisor, false); 120 | | } 121 | | 122 | * | function toFactor(int256 value, uint256 divisor) internal pure returns (int256) { 123 | * | uint256 result = toFactor(value.abs(), divisor); 124 | * | return value > 0 ? result.toInt256() : -result.toInt256(); 125 | | } 126 | | 127 | | /** 128 | | * Converts the given value from float to wei. 129 | | * 130 | | * @param value The value to convert. 131 | | * @return The converted value in wei. 132 | | */ 133 | * | function floatToWei(uint256 value) internal pure returns (uint256) { 134 | * | return value / FLOAT_TO_WEI_DIVISOR; 135 | | } 136 | | 137 | | /** 138 | | * Converts the given value from wei to float. 139 | | * 140 | | * @param value The value to convert. 141 | | * @return The converted value in float. 142 | | */ 143 | * | function weiToFloat(uint256 value) internal pure returns (uint256) { 144 | * | return value * FLOAT_TO_WEI_DIVISOR; 145 | | } 146 | | 147 | | /** 148 | | * Converts the given number of basis points to float. 149 | | * 150 | | * @param basisPoints The number of basis points to convert. 151 | | * @return The converted value in float. 152 | | */ 153 | * | function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) { 154 | * | return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR; 155 | | } 156 | | } 157 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Printer.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 6 | | 7 | | /** 8 | | * @title Printer 9 | | * @dev Library for console functions 10 | | */ 11 | * | library Printer { 12 | | using SafeCast for int256; 13 | | 14 | | function log(string memory str) internal pure { 15 | | } 16 | | 17 | | function log(string memory label, int256 value) internal pure { 18 | | if (value < 0) { 19 | | } else { 20 | | } 21 | | } 22 | | } 23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/utils/Uint256Mask.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../error/Errors.sol"; 6 | | 7 | * | library Uint256Mask { 8 | | struct Mask { 9 | | uint256 bits; 10 | | } 11 | | 12 | | function validateUniqueAndSetIndex( 13 | | Mask memory mask, 14 | | uint256 index, 15 | | string memory label 16 | | ) internal pure { 17 | | if (index >= 256) { 18 | | revert Errors.MaskIndexOutOfBounds(index, label); 19 | | } 20 | | 21 | | uint256 bit = 1 << index; 22 | | 23 | | if (mask.bits & bit != 0) { 24 | | revert Errors.DuplicatedIndex(index, label); 25 | | } 26 | | 27 | | mask.bits = mask.bits | bit; 28 | | } 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/v1/IRouterV1.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | interface IRouterV1 { 6 | | function swap(address[] memory _path, uint256 _amountIn, uint256 _minOut, address _receiver) external; 7 | | } 8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/v1/IVaultV1.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | interface IVaultV1 { 6 | | function allWhitelistedTokensLength() external view returns (uint256); 7 | | function allWhitelistedTokens(uint256) external view returns (address); 8 | | function withdrawFees(address _token, address _receiver) external returns (uint256); 9 | | } 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/ExecuteWithdrawalUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../adl/AdlUtils.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | 9 | | import "./WithdrawalVault.sol"; 10 | | import "./WithdrawalStoreUtils.sol"; 11 | | import "./WithdrawalEventUtils.sol"; 12 | | 13 | | import "../nonce/NonceUtils.sol"; 14 | | import "../pricing/SwapPricingUtils.sol"; 15 | | import "../oracle/Oracle.sol"; 16 | | import "../oracle/OracleUtils.sol"; 17 | | 18 | | import "../gas/GasUtils.sol"; 19 | | import "../callback/CallbackUtils.sol"; 20 | | 21 | | import "../utils/Array.sol"; 22 | | import "../utils/AccountUtils.sol"; 23 | | 24 | * | library ExecuteWithdrawalUtils { 25 | | using SafeCast for uint256; 26 | | using SafeCast for int256; 27 | | using Array for uint256[]; 28 | | using Price for Price.Props; 29 | | using Withdrawal for Withdrawal.Props; 30 | | 31 | | using EventUtils for EventUtils.AddressItems; 32 | | using EventUtils for EventUtils.UintItems; 33 | | using EventUtils for EventUtils.IntItems; 34 | | using EventUtils for EventUtils.BoolItems; 35 | | using EventUtils for EventUtils.Bytes32Items; 36 | | using EventUtils for EventUtils.BytesItems; 37 | | using EventUtils for EventUtils.StringItems; 38 | | 39 | | struct ExecuteWithdrawalParams { 40 | | DataStore dataStore; 41 | | EventEmitter eventEmitter; 42 | | WithdrawalVault withdrawalVault; 43 | | Oracle oracle; 44 | | bytes32 key; 45 | | address keeper; 46 | | uint256 startingGas; 47 | | ISwapPricingUtils.SwapPricingType swapPricingType; 48 | | } 49 | | 50 | | struct ExecuteWithdrawalCache { 51 | | uint256 requestExpirationTime; 52 | | uint256 maxOracleTimestamp; 53 | | uint256 marketTokensBalance; 54 | | Market.Props market; 55 | | MarketUtils.MarketPrices prices; 56 | | } 57 | | 58 | | struct _ExecuteWithdrawalCache { 59 | | uint256 longTokenOutputAmount; 60 | | uint256 shortTokenOutputAmount; 61 | | SwapPricingUtils.SwapFees longTokenFees; 62 | | SwapPricingUtils.SwapFees shortTokenFees; 63 | | uint256 longTokenPoolAmountDelta; 64 | | uint256 shortTokenPoolAmountDelta; 65 | | } 66 | | 67 | | struct ExecuteWithdrawalResult { 68 | | address outputToken; 69 | | uint256 outputAmount; 70 | | address secondaryOutputToken; 71 | | uint256 secondaryOutputAmount; 72 | | } 73 | | 74 | | struct SwapCache { 75 | | Market.Props[] swapPathMarkets; 76 | | SwapUtils.SwapParams swapParams; 77 | | address outputToken; 78 | | uint256 outputAmount; 79 | | } 80 | | 81 | | /** 82 | | * Executes a withdrawal on the market. 83 | | * 84 | | * @param params The parameters for executing the withdrawal. 85 | | */ 86 | * | function executeWithdrawal(ExecuteWithdrawalParams memory params, Withdrawal.Props memory withdrawal) internal { 87 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 88 | * | params.startingGas -= gasleft() / 63; 89 | | 90 | * | WithdrawalStoreUtils.remove(params.dataStore, params.key, withdrawal.account()); 91 | | 92 | * | if (withdrawal.account() == address(0)) { 93 | | revert Errors.EmptyWithdrawal(); 94 | | } 95 | * | if (withdrawal.marketTokenAmount() == 0) { 96 | | revert Errors.EmptyWithdrawalAmount(); 97 | | } 98 | | 99 | * | if (params.oracle.minTimestamp() < withdrawal.updatedAtTime()) { 100 | | revert Errors.OracleTimestampsAreSmallerThanRequired( 101 | | params.oracle.minTimestamp(), 102 | | withdrawal.updatedAtTime() 103 | | ); 104 | | } 105 | | 106 | * | ExecuteWithdrawalCache memory cache; 107 | | 108 | * | cache.requestExpirationTime = params.dataStore.getUint(Keys.REQUEST_EXPIRATION_TIME); 109 | * | cache.maxOracleTimestamp = params.oracle.maxTimestamp(); 110 | | 111 | * | if (cache.maxOracleTimestamp > withdrawal.updatedAtTime() + cache.requestExpirationTime) { 112 | * | revert Errors.OracleTimestampsAreLargerThanRequestExpirationTime( 113 | * | cache.maxOracleTimestamp, 114 | * | withdrawal.updatedAtTime(), 115 | * | cache.requestExpirationTime 116 | | ); 117 | | } 118 | | 119 | * | MarketUtils.distributePositionImpactPool( 120 | * | params.dataStore, 121 | * | params.eventEmitter, 122 | * | withdrawal.market() 123 | | ); 124 | | 125 | * | cache.market = MarketUtils.getEnabledMarket(params.dataStore, withdrawal.market()); 126 | * | cache.prices = MarketUtils.getMarketPrices( 127 | * | params.oracle, 128 | * | cache.market 129 | | ); 130 | | 131 | * | PositionUtils.updateFundingAndBorrowingState( 132 | * | params.dataStore, 133 | * | params.eventEmitter, 134 | * | cache.market, 135 | * | cache.prices 136 | | ); 137 | | 138 | * | cache.marketTokensBalance = MarketToken(payable(withdrawal.market())).balanceOf(address(params.withdrawalVault)); 139 | * | if (cache.marketTokensBalance < withdrawal.marketTokenAmount()) { 140 | | revert Errors.InsufficientMarketTokens(cache.marketTokensBalance, withdrawal.marketTokenAmount()); 141 | | } 142 | | 143 | * | ExecuteWithdrawalResult memory result = _executeWithdrawal( 144 | * | params, 145 | * | withdrawal, 146 | * | cache.market, 147 | * | cache.prices 148 | | ); 149 | | 150 | * | WithdrawalEventUtils.emitWithdrawalExecuted( 151 | * | params.eventEmitter, 152 | * | params.key, 153 | * | withdrawal.account(), 154 | * | params.swapPricingType 155 | | ); 156 | | 157 | * | EventUtils.EventLogData memory eventData; 158 | * | eventData.addressItems.initItems(2); 159 | * | eventData.addressItems.setItem(0, "outputToken", result.outputToken); 160 | * | eventData.addressItems.setItem(1, "secondaryOutputToken", result.secondaryOutputToken); 161 | * | eventData.uintItems.initItems(2); 162 | * | eventData.uintItems.setItem(0, "outputAmount", result.outputAmount); 163 | * | eventData.uintItems.setItem(1, "secondaryOutputAmount", result.secondaryOutputAmount); 164 | * | CallbackUtils.afterWithdrawalExecution(params.key, withdrawal, eventData); 165 | | 166 | * | GasUtils.payExecutionFee( 167 | * | params.dataStore, 168 | * | params.eventEmitter, 169 | * | params.withdrawalVault, 170 | * | params.key, 171 | * | withdrawal.callbackContract(), 172 | * | withdrawal.executionFee(), 173 | * | params.startingGas, 174 | * | GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length), 175 | * | params.keeper, 176 | * | withdrawal.receiver() 177 | | ); 178 | | } 179 | | 180 | | /** 181 | | * @dev executes a withdrawal. 182 | | * @param params ExecuteWithdrawalParams. 183 | | * @param withdrawal The withdrawal to execute. 184 | | */ 185 | * | function _executeWithdrawal( 186 | | ExecuteWithdrawalParams memory params, 187 | | Withdrawal.Props memory withdrawal, 188 | | Market.Props memory market, 189 | | MarketUtils.MarketPrices memory prices 190 | * | ) internal returns (ExecuteWithdrawalResult memory) { 191 | * | _ExecuteWithdrawalCache memory cache; 192 | | 193 | * | (cache.longTokenOutputAmount, cache.shortTokenOutputAmount) = _getOutputAmounts(params, market, prices, withdrawal.marketTokenAmount()); 194 | | 195 | * | cache.longTokenFees = SwapPricingUtils.getSwapFees( 196 | * | params.dataStore, 197 | * | market.marketToken, 198 | * | cache.longTokenOutputAmount, 199 | * | false, // forPositiveImpact 200 | * | withdrawal.uiFeeReceiver(), 201 | * | params.swapPricingType 202 | | ); 203 | | 204 | * | FeeUtils.incrementClaimableFeeAmount( 205 | * | params.dataStore, 206 | * | params.eventEmitter, 207 | * | market.marketToken, 208 | * | market.longToken, 209 | * | cache.longTokenFees.feeReceiverAmount, 210 | | Keys.WITHDRAWAL_FEE_TYPE 211 | | ); 212 | | 213 | * | FeeUtils.incrementClaimableUiFeeAmount( 214 | * | params.dataStore, 215 | * | params.eventEmitter, 216 | * | withdrawal.uiFeeReceiver(), 217 | * | market.marketToken, 218 | * | market.longToken, 219 | * | cache.longTokenFees.uiFeeAmount, 220 | | Keys.UI_WITHDRAWAL_FEE_TYPE 221 | | ); 222 | | 223 | * | cache.shortTokenFees = SwapPricingUtils.getSwapFees( 224 | * | params.dataStore, 225 | * | market.marketToken, 226 | * | cache.shortTokenOutputAmount, 227 | * | false, // forPositiveImpact 228 | * | withdrawal.uiFeeReceiver(), 229 | * | params.swapPricingType 230 | | ); 231 | | 232 | * | FeeUtils.incrementClaimableFeeAmount( 233 | * | params.dataStore, 234 | * | params.eventEmitter, 235 | * | market.marketToken, 236 | * | market.shortToken, 237 | * | cache.shortTokenFees.feeReceiverAmount, 238 | | Keys.WITHDRAWAL_FEE_TYPE 239 | | ); 240 | | 241 | * | FeeUtils.incrementClaimableUiFeeAmount( 242 | * | params.dataStore, 243 | * | params.eventEmitter, 244 | * | withdrawal.uiFeeReceiver(), 245 | * | market.marketToken, 246 | * | market.shortToken, 247 | * | cache.shortTokenFees.uiFeeAmount, 248 | | Keys.UI_WITHDRAWAL_FEE_TYPE 249 | | ); 250 | | 251 | | // the pool will be reduced by the outputAmount minus the fees for the pool 252 | * | cache.longTokenPoolAmountDelta = cache.longTokenOutputAmount - cache.longTokenFees.feeAmountForPool; 253 | * | cache.longTokenOutputAmount = cache.longTokenFees.amountAfterFees; 254 | | 255 | * | cache.shortTokenPoolAmountDelta = cache.shortTokenOutputAmount - cache.shortTokenFees.feeAmountForPool; 256 | * | cache.shortTokenOutputAmount = cache.shortTokenFees.amountAfterFees; 257 | | 258 | | // it is rare but possible for withdrawals to be blocked because pending borrowing fees 259 | | // have not yet been deducted from position collateral and credited to the poolAmount value 260 | * | MarketUtils.applyDeltaToPoolAmount( 261 | * | params.dataStore, 262 | * | params.eventEmitter, 263 | * | market, 264 | * | market.longToken, 265 | * | -cache.longTokenPoolAmountDelta.toInt256() 266 | | ); 267 | | 268 | * | MarketUtils.applyDeltaToPoolAmount( 269 | * | params.dataStore, 270 | * | params.eventEmitter, 271 | * | market, 272 | * | market.shortToken, 273 | * | -cache.shortTokenPoolAmountDelta.toInt256() 274 | | ); 275 | | 276 | * | MarketUtils.validateReserve( 277 | * | params.dataStore, 278 | * | market, 279 | * | prices, 280 | * | true 281 | | ); 282 | | 283 | * | MarketUtils.validateReserve( 284 | * | params.dataStore, 285 | * | market, 286 | * | prices, 287 | * | false 288 | | ); 289 | | 290 | * | MarketUtils.validateMaxPnl( 291 | * | params.dataStore, 292 | * | market, 293 | * | prices, 294 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, 295 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS 296 | | ); 297 | | 298 | * | MarketToken(payable(market.marketToken)).burn( 299 | * | address(params.withdrawalVault), 300 | * | withdrawal.marketTokenAmount() 301 | | ); 302 | | 303 | * | params.withdrawalVault.syncTokenBalance(market.marketToken); 304 | | 305 | * | ExecuteWithdrawalResult memory result; 306 | * | (result.outputToken, result.outputAmount) = _swap( 307 | * | params, 308 | * | market, 309 | * | market.longToken, 310 | * | cache.longTokenOutputAmount, 311 | * | withdrawal.longTokenSwapPath(), 312 | * | withdrawal.minLongTokenAmount(), 313 | * | withdrawal.receiver(), 314 | * | withdrawal.uiFeeReceiver(), 315 | * | withdrawal.shouldUnwrapNativeToken() 316 | | ); 317 | | 318 | * | (result.secondaryOutputToken, result.secondaryOutputAmount) = _swap( 319 | * | params, 320 | * | market, 321 | * | market.shortToken, 322 | * | cache.shortTokenOutputAmount, 323 | * | withdrawal.shortTokenSwapPath(), 324 | * | withdrawal.minShortTokenAmount(), 325 | * | withdrawal.receiver(), 326 | * | withdrawal.uiFeeReceiver(), 327 | * | withdrawal.shouldUnwrapNativeToken() 328 | | ); 329 | | 330 | * | SwapPricingUtils.emitSwapFeesCollected( 331 | * | params.eventEmitter, 332 | * | params.key, 333 | * | market.marketToken, 334 | * | market.longToken, 335 | * | prices.longTokenPrice.min, 336 | | Keys.WITHDRAWAL_FEE_TYPE, 337 | * | cache.longTokenFees 338 | | ); 339 | | 340 | * | SwapPricingUtils.emitSwapFeesCollected( 341 | * | params.eventEmitter, 342 | * | params.key, 343 | * | market.marketToken, 344 | * | market.shortToken, 345 | * | prices.shortTokenPrice.min, 346 | | Keys.WITHDRAWAL_FEE_TYPE, 347 | * | cache.shortTokenFees 348 | | ); 349 | | 350 | | // if the native token was transferred to the receiver in a swap 351 | | // it may be possible to invoke internal contracts before the validations 352 | | // are called 353 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, market); 354 | | 355 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 356 | * | params.dataStore, 357 | * | market, 358 | * | prices.indexTokenPrice, 359 | * | prices.longTokenPrice, 360 | * | prices.shortTokenPrice, 361 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, 362 | * | false 363 | | ); 364 | | 365 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken))); 366 | | 367 | * | MarketEventUtils.emitMarketPoolValueUpdated( 368 | * | params.eventEmitter, 369 | * | keccak256(abi.encode("WITHDRAWAL")), 370 | * | params.key, 371 | * | market.marketToken, 372 | * | poolValueInfo, 373 | * | marketTokensSupply 374 | | ); 375 | | 376 | * | return result; 377 | | } 378 | | 379 | * | function _swap( 380 | | ExecuteWithdrawalParams memory params, 381 | | Market.Props memory market, 382 | | address tokenIn, 383 | | uint256 amountIn, 384 | | address[] memory swapPath, 385 | | uint256 minOutputAmount, 386 | | address receiver, 387 | | address uiFeeReceiver, 388 | | bool shouldUnwrapNativeToken 389 | * | ) internal returns (address, uint256) { 390 | * | SwapCache memory cache; 391 | | 392 | * | cache.swapPathMarkets = MarketUtils.getSwapPathMarkets(params.dataStore, swapPath); 393 | | 394 | * | cache.swapParams.dataStore = params.dataStore; 395 | * | cache.swapParams.eventEmitter = params.eventEmitter; 396 | * | cache.swapParams.oracle = params.oracle; 397 | * | cache.swapParams.bank = Bank(payable(market.marketToken)); 398 | * | cache.swapParams.key = params.key; 399 | * | cache.swapParams.tokenIn = tokenIn; 400 | * | cache.swapParams.amountIn = amountIn; 401 | * | cache.swapParams.swapPathMarkets = cache.swapPathMarkets; 402 | * | cache.swapParams.minOutputAmount = minOutputAmount; 403 | * | cache.swapParams.receiver = receiver; 404 | * | cache.swapParams.uiFeeReceiver = uiFeeReceiver; 405 | * | cache.swapParams.shouldUnwrapNativeToken = shouldUnwrapNativeToken; 406 | | 407 | * | (cache.outputToken, cache.outputAmount) = SwapUtils.swap(cache.swapParams); 408 | | 409 | | // validate that internal state changes are correct before calling 410 | | // internal callbacks 411 | * | MarketUtils.validateMarketTokenBalance(params.dataStore, cache.swapPathMarkets); 412 | | 413 | * | return (cache.outputToken, cache.outputAmount); 414 | | } 415 | | 416 | * | function _getOutputAmounts( 417 | | ExecuteWithdrawalParams memory params, 418 | | Market.Props memory market, 419 | | MarketUtils.MarketPrices memory prices, 420 | | uint256 marketTokenAmount 421 | * | ) internal returns (uint256, uint256) { 422 | | // the max pnl factor for withdrawals should be the lower of the max pnl factor values 423 | | // which means that pnl would be capped to a smaller amount and the pool 424 | | // value would be higher even if there is a large pnl 425 | | // this should be okay since MarketUtils.validateMaxPnl is called after the withdrawal 426 | | // which ensures that the max pnl factor for withdrawals was not exceeded 427 | * | MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo( 428 | * | params.dataStore, 429 | * | market, 430 | * | params.oracle.getPrimaryPrice(market.indexToken), 431 | * | prices.longTokenPrice, 432 | * | prices.shortTokenPrice, 433 | | Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS, 434 | * | false 435 | | ); 436 | | 437 | * | if (poolValueInfo.poolValue <= 0) { 438 | | revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue); 439 | | } 440 | | 441 | * | uint256 poolValue = poolValueInfo.poolValue.toUint256(); 442 | * | uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken))); 443 | | 444 | * | MarketEventUtils.emitMarketPoolValueInfo( 445 | * | params.eventEmitter, 446 | * | params.key, 447 | * | market.marketToken, 448 | * | poolValueInfo, 449 | * | marketTokensSupply 450 | | ); 451 | | 452 | * | uint256 longTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.longToken); 453 | * | uint256 shortTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.shortToken); 454 | | 455 | * | uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max; 456 | * | uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max; 457 | | 458 | * | uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd; 459 | | 460 | * | uint256 marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, poolValue, marketTokensSupply); 461 | | 462 | * | uint256 longTokenOutputUsd = Precision.mulDiv(marketTokensUsd, longTokenPoolUsd, totalPoolUsd); 463 | * | uint256 shortTokenOutputUsd = Precision.mulDiv(marketTokensUsd, shortTokenPoolUsd, totalPoolUsd); 464 | | 465 | * | return ( 466 | * | longTokenOutputUsd / prices.longTokenPrice.max, 467 | * | shortTokenOutputUsd / prices.shortTokenPrice.max 468 | | ); 469 | | } 470 | | } 471 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/Withdrawal.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | /** 6 | | * @title Withdrawal 7 | | * @dev Struct for withdrawals 8 | | */ 9 | * | library Withdrawal { 10 | | // @dev there is a limit on the number of fields a struct can have when being passed 11 | | // or returned as a memory variable which can cause "Stack too deep" errors 12 | | // use sub-structs to avoid this issue 13 | | // @param addresses address values 14 | | // @param numbers number values 15 | | // @param flags boolean values 16 | | struct Props { 17 | | Addresses addresses; 18 | | Numbers numbers; 19 | | Flags flags; 20 | | } 21 | | 22 | | // @param account The account to withdraw for. 23 | | // @param receiver The address that will receive the withdrawn tokens. 24 | | // @param callbackContract The contract that will be called back. 25 | | // @param uiFeeReceiver The ui fee receiver. 26 | | // @param market The market on which the withdrawal will be executed. 27 | | struct Addresses { 28 | | address account; 29 | | address receiver; 30 | | address callbackContract; 31 | | address uiFeeReceiver; 32 | | address market; 33 | | address[] longTokenSwapPath; 34 | | address[] shortTokenSwapPath; 35 | | } 36 | | 37 | | // @param marketTokenAmount The amount of market tokens that will be withdrawn. 38 | | // @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn. 39 | | // @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn. 40 | | // @param updatedAtBlock The block at which the withdrawal was last updated. 41 | | // @param executionFee The execution fee for the withdrawal. 42 | | // @param callbackGasLimit The gas limit for calling the callback contract. 43 | | struct Numbers { 44 | | uint256 marketTokenAmount; 45 | | uint256 minLongTokenAmount; 46 | | uint256 minShortTokenAmount; 47 | | uint256 updatedAtBlock; 48 | | uint256 updatedAtTime; 49 | | uint256 executionFee; 50 | | uint256 callbackGasLimit; 51 | | } 52 | | 53 | | // @param shouldUnwrapNativeToken whether to unwrap the native token when 54 | | struct Flags { 55 | | bool shouldUnwrapNativeToken; 56 | | } 57 | | 58 | * | function account(Props memory props) internal pure returns (address) { 59 | * | return props.addresses.account; 60 | | } 61 | | 62 | * | function setAccount(Props memory props, address value) internal pure { 63 | * | props.addresses.account = value; 64 | | } 65 | | 66 | * | function receiver(Props memory props) internal pure returns (address) { 67 | * | return props.addresses.receiver; 68 | | } 69 | | 70 | * | function setReceiver(Props memory props, address value) internal pure { 71 | * | props.addresses.receiver = value; 72 | | } 73 | | 74 | * | function callbackContract(Props memory props) internal pure returns (address) { 75 | * | return props.addresses.callbackContract; 76 | | } 77 | | 78 | * | function setCallbackContract(Props memory props, address value) internal pure { 79 | * | props.addresses.callbackContract = value; 80 | | } 81 | | 82 | * | function uiFeeReceiver(Props memory props) internal pure returns (address) { 83 | * | return props.addresses.uiFeeReceiver; 84 | | } 85 | | 86 | * | function setUiFeeReceiver(Props memory props, address value) internal pure { 87 | * | props.addresses.uiFeeReceiver = value; 88 | | } 89 | | 90 | * | function market(Props memory props) internal pure returns (address) { 91 | * | return props.addresses.market; 92 | | } 93 | | 94 | * | function setMarket(Props memory props, address value) internal pure { 95 | * | props.addresses.market = value; 96 | | } 97 | | 98 | * | function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 99 | * | return props.addresses.longTokenSwapPath; 100 | | } 101 | | 102 | * | function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure { 103 | * | props.addresses.longTokenSwapPath = value; 104 | | } 105 | | 106 | * | function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) { 107 | * | return props.addresses.shortTokenSwapPath; 108 | | } 109 | | 110 | * | function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure { 111 | * | props.addresses.shortTokenSwapPath = value; 112 | | } 113 | | 114 | * | function marketTokenAmount(Props memory props) internal pure returns (uint256) { 115 | * | return props.numbers.marketTokenAmount; 116 | | } 117 | | 118 | * | function setMarketTokenAmount(Props memory props, uint256 value) internal pure { 119 | * | props.numbers.marketTokenAmount = value; 120 | | } 121 | | 122 | * | function minLongTokenAmount(Props memory props) internal pure returns (uint256) { 123 | * | return props.numbers.minLongTokenAmount; 124 | | } 125 | | 126 | * | function setMinLongTokenAmount(Props memory props, uint256 value) internal pure { 127 | * | props.numbers.minLongTokenAmount = value; 128 | | } 129 | | 130 | * | function minShortTokenAmount(Props memory props) internal pure returns (uint256) { 131 | * | return props.numbers.minShortTokenAmount; 132 | | } 133 | | 134 | * | function setMinShortTokenAmount(Props memory props, uint256 value) internal pure { 135 | * | props.numbers.minShortTokenAmount = value; 136 | | } 137 | | 138 | * | function updatedAtBlock(Props memory props) internal pure returns (uint256) { 139 | * | return props.numbers.updatedAtBlock; 140 | | } 141 | | 142 | * | function setUpdatedAtBlock(Props memory props, uint256 value) internal pure { 143 | * | props.numbers.updatedAtBlock = value; 144 | | } 145 | | 146 | * | function updatedAtTime(Props memory props) internal pure returns (uint256) { 147 | * | return props.numbers.updatedAtTime; 148 | | } 149 | | 150 | * | function setUpdatedAtTime(Props memory props, uint256 value) internal pure { 151 | * | props.numbers.updatedAtTime = value; 152 | | } 153 | | 154 | * | function executionFee(Props memory props) internal pure returns (uint256) { 155 | * | return props.numbers.executionFee; 156 | | } 157 | | 158 | * | function setExecutionFee(Props memory props, uint256 value) internal pure { 159 | * | props.numbers.executionFee = value; 160 | | } 161 | | 162 | * | function callbackGasLimit(Props memory props) internal pure returns (uint256) { 163 | * | return props.numbers.callbackGasLimit; 164 | | } 165 | | 166 | * | function setCallbackGasLimit(Props memory props, uint256 value) internal pure { 167 | * | props.numbers.callbackGasLimit = value; 168 | | } 169 | | 170 | * | function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) { 171 | * | return props.flags.shouldUnwrapNativeToken; 172 | | } 173 | | 174 | * | function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure { 175 | * | props.flags.shouldUnwrapNativeToken = value; 176 | | } 177 | | } 178 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalEventUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../event/EventEmitter.sol"; 6 | | import "../event/EventUtils.sol"; 7 | | import "../utils/Cast.sol"; 8 | | 9 | | import "./Withdrawal.sol"; 10 | | import "./WithdrawalUtils.sol"; 11 | | import "../pricing/ISwapPricingUtils.sol"; 12 | | 13 | * | library WithdrawalEventUtils { 14 | | using Withdrawal for Withdrawal.Props; 15 | | 16 | | using EventUtils for EventUtils.AddressItems; 17 | | using EventUtils for EventUtils.UintItems; 18 | | using EventUtils for EventUtils.IntItems; 19 | | using EventUtils for EventUtils.BoolItems; 20 | | using EventUtils for EventUtils.Bytes32Items; 21 | | using EventUtils for EventUtils.BytesItems; 22 | | using EventUtils for EventUtils.StringItems; 23 | | 24 | * | function emitWithdrawalCreated( 25 | | EventEmitter eventEmitter, 26 | | bytes32 key, 27 | | Withdrawal.Props memory withdrawal, 28 | | WithdrawalUtils.WithdrawalType withdrawalType 29 | * | ) internal { 30 | * | EventUtils.EventLogData memory eventData; 31 | | 32 | * | eventData.addressItems.initItems(4); 33 | * | eventData.addressItems.setItem(0, "account", withdrawal.account()); 34 | * | eventData.addressItems.setItem(1, "receiver", withdrawal.receiver()); 35 | * | eventData.addressItems.setItem(2, "callbackContract", withdrawal.callbackContract()); 36 | * | eventData.addressItems.setItem(3, "market", withdrawal.market()); 37 | | 38 | * | eventData.addressItems.initArrayItems(2); 39 | * | eventData.addressItems.setItem(0, "longTokenSwapPath", withdrawal.longTokenSwapPath()); 40 | * | eventData.addressItems.setItem(1, "shortTokenSwapPath", withdrawal.shortTokenSwapPath()); 41 | | 42 | * | eventData.uintItems.initItems(8); 43 | * | eventData.uintItems.setItem(0, "marketTokenAmount", withdrawal.marketTokenAmount()); 44 | * | eventData.uintItems.setItem(1, "minLongTokenAmount", withdrawal.minLongTokenAmount()); 45 | * | eventData.uintItems.setItem(2, "minShortTokenAmount", withdrawal.minShortTokenAmount()); 46 | * | eventData.uintItems.setItem(3, "updatedAtBlock", withdrawal.updatedAtBlock()); 47 | * | eventData.uintItems.setItem(4, "updatedAtTime", withdrawal.updatedAtTime()); 48 | * | eventData.uintItems.setItem(5, "executionFee", withdrawal.executionFee()); 49 | * | eventData.uintItems.setItem(6, "callbackGasLimit", withdrawal.callbackGasLimit()); 50 | * | eventData.uintItems.setItem(7, "withdrawalType", uint256(withdrawalType)); 51 | | 52 | * | eventData.boolItems.initItems(1); 53 | * | eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", withdrawal.shouldUnwrapNativeToken()); 54 | | 55 | * | eventData.bytes32Items.initItems(1); 56 | * | eventData.bytes32Items.setItem(0, "key", key); 57 | | 58 | * | eventEmitter.emitEventLog2( 59 | | "WithdrawalCreated", 60 | * | key, 61 | * | Cast.toBytes32(withdrawal.account()), 62 | * | eventData 63 | | ); 64 | | } 65 | | 66 | * | function emitWithdrawalExecuted( 67 | | EventEmitter eventEmitter, 68 | | bytes32 key, 69 | | address account, 70 | | ISwapPricingUtils.SwapPricingType swapPricingType 71 | * | ) internal { 72 | * | EventUtils.EventLogData memory eventData; 73 | | 74 | * | eventData.bytes32Items.initItems(1); 75 | * | eventData.bytes32Items.setItem(0, "key", key); 76 | | 77 | * | eventData.addressItems.initItems(1); 78 | * | eventData.addressItems.setItem(0, "account", account); 79 | | 80 | * | eventData.uintItems.initItems(1); 81 | * | eventData.uintItems.setItem(0, "swapPricingType", uint256(swapPricingType)); 82 | | 83 | * | eventEmitter.emitEventLog2( 84 | | "WithdrawalExecuted", 85 | * | key, 86 | * | Cast.toBytes32(account), 87 | * | eventData 88 | | ); 89 | | } 90 | | 91 | * | function emitWithdrawalCancelled( 92 | | EventEmitter eventEmitter, 93 | | bytes32 key, 94 | | address account, 95 | | string memory reason, 96 | | bytes memory reasonBytes 97 | * | ) internal { 98 | * | EventUtils.EventLogData memory eventData; 99 | | 100 | * | eventData.bytes32Items.initItems(1); 101 | * | eventData.bytes32Items.setItem(0, "key", key); 102 | | 103 | * | eventData.addressItems.initItems(1); 104 | * | eventData.addressItems.setItem(0, "account", account); 105 | | 106 | * | eventData.stringItems.initItems(1); 107 | * | eventData.stringItems.setItem(0, "reason", reason); 108 | | 109 | * | eventData.bytesItems.initItems(1); 110 | * | eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes); 111 | | 112 | * | eventEmitter.emitEventLog2( 113 | | "WithdrawalCancelled", 114 | * | key, 115 | * | Cast.toBytes32(account), 116 | * | eventData 117 | | ); 118 | | } 119 | | } 120 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalStoreUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../data/Keys.sol"; 6 | | import "../data/DataStore.sol"; 7 | | 8 | | import "./Withdrawal.sol"; 9 | | 10 | | /** 11 | | * @title WithdrawalStoreUtils 12 | | * @dev Library for withdrawal storage functions 13 | | */ 14 | * | library WithdrawalStoreUtils { 15 | | using Withdrawal for Withdrawal.Props; 16 | | 17 | * | bytes32 internal constant ACCOUNT = keccak256(abi.encode("ACCOUNT")); 18 | * | bytes32 internal constant RECEIVER = keccak256(abi.encode("RECEIVER")); 19 | * | bytes32 internal constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT")); 20 | * | bytes32 internal constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER")); 21 | * | bytes32 internal constant MARKET = keccak256(abi.encode("MARKET")); 22 | * | bytes32 internal constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH")); 23 | * | bytes32 internal constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH")); 24 | | 25 | * | bytes32 internal constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode("MARKET_TOKEN_AMOUNT")); 26 | * | bytes32 internal constant MIN_LONG_TOKEN_AMOUNT = keccak256(abi.encode("MIN_LONG_TOKEN_AMOUNT")); 27 | * | bytes32 internal constant MIN_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("MIN_SHORT_TOKEN_AMOUNT")); 28 | * | bytes32 internal constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK")); 29 | * | bytes32 internal constant UPDATED_AT_TIME = keccak256(abi.encode("UPDATED_AT_TIME")); 30 | * | bytes32 internal constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE")); 31 | * | bytes32 internal constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT")); 32 | | 33 | * | bytes32 internal constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN")); 34 | | 35 | * | function get(DataStore dataStore, bytes32 key) internal view returns (Withdrawal.Props memory) { 36 | * | Withdrawal.Props memory withdrawal; 37 | * | if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) { 38 | * | return withdrawal; 39 | | } 40 | | 41 | * | withdrawal.setAccount(dataStore.getAddress( 42 | * | keccak256(abi.encode(key, ACCOUNT)) 43 | | )); 44 | | 45 | * | withdrawal.setReceiver(dataStore.getAddress( 46 | * | keccak256(abi.encode(key, RECEIVER)) 47 | | )); 48 | | 49 | * | withdrawal.setCallbackContract(dataStore.getAddress( 50 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 51 | | )); 52 | | 53 | * | withdrawal.setUiFeeReceiver(dataStore.getAddress( 54 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 55 | | )); 56 | | 57 | * | withdrawal.setMarket(dataStore.getAddress( 58 | * | keccak256(abi.encode(key, MARKET)) 59 | | )); 60 | | 61 | * | withdrawal.setLongTokenSwapPath(dataStore.getAddressArray( 62 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 63 | | )); 64 | | 65 | * | withdrawal.setShortTokenSwapPath(dataStore.getAddressArray( 66 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 67 | | )); 68 | | 69 | * | withdrawal.setMarketTokenAmount(dataStore.getUint( 70 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)) 71 | | )); 72 | | 73 | * | withdrawal.setMinLongTokenAmount(dataStore.getUint( 74 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)) 75 | | )); 76 | | 77 | * | withdrawal.setMinShortTokenAmount(dataStore.getUint( 78 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)) 79 | | )); 80 | | 81 | * | withdrawal.setUpdatedAtBlock(dataStore.getUint( 82 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 83 | | )); 84 | | 85 | * | withdrawal.setUpdatedAtTime(dataStore.getUint( 86 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 87 | | )); 88 | | 89 | * | withdrawal.setExecutionFee(dataStore.getUint( 90 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 91 | | )); 92 | | 93 | * | withdrawal.setCallbackGasLimit(dataStore.getUint( 94 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 95 | | )); 96 | | 97 | * | withdrawal.setShouldUnwrapNativeToken(dataStore.getBool( 98 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 99 | | )); 100 | | 101 | * | return withdrawal; 102 | | } 103 | | 104 | * | function set(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) internal { 105 | * | dataStore.addBytes32( 106 | | Keys.WITHDRAWAL_LIST, 107 | * | key 108 | | ); 109 | | 110 | * | dataStore.addBytes32( 111 | * | Keys.accountWithdrawalListKey(withdrawal.account()), 112 | * | key 113 | | ); 114 | | 115 | * | dataStore.setAddress( 116 | * | keccak256(abi.encode(key, ACCOUNT)), 117 | * | withdrawal.account() 118 | | ); 119 | | 120 | * | dataStore.setAddress( 121 | * | keccak256(abi.encode(key, RECEIVER)), 122 | * | withdrawal.receiver() 123 | | ); 124 | | 125 | * | dataStore.setAddress( 126 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)), 127 | * | withdrawal.callbackContract() 128 | | ); 129 | | 130 | * | dataStore.setAddress( 131 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)), 132 | * | withdrawal.uiFeeReceiver() 133 | | ); 134 | | 135 | * | dataStore.setAddress( 136 | * | keccak256(abi.encode(key, MARKET)), 137 | * | withdrawal.market() 138 | | ); 139 | | 140 | * | dataStore.setAddressArray( 141 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)), 142 | * | withdrawal.longTokenSwapPath() 143 | | ); 144 | | 145 | * | dataStore.setAddressArray( 146 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)), 147 | * | withdrawal.shortTokenSwapPath() 148 | | ); 149 | | 150 | * | dataStore.setUint( 151 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)), 152 | * | withdrawal.marketTokenAmount() 153 | | ); 154 | | 155 | * | dataStore.setUint( 156 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)), 157 | * | withdrawal.minLongTokenAmount() 158 | | ); 159 | | 160 | * | dataStore.setUint( 161 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)), 162 | * | withdrawal.minShortTokenAmount() 163 | | ); 164 | | 165 | * | dataStore.setUint( 166 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)), 167 | * | withdrawal.updatedAtBlock() 168 | | ); 169 | | 170 | * | dataStore.setUint( 171 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)), 172 | * | withdrawal.updatedAtTime() 173 | | ); 174 | | 175 | * | dataStore.setUint( 176 | * | keccak256(abi.encode(key, EXECUTION_FEE)), 177 | * | withdrawal.executionFee() 178 | | ); 179 | | 180 | * | dataStore.setUint( 181 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)), 182 | * | withdrawal.callbackGasLimit() 183 | | ); 184 | | 185 | * | dataStore.setBool( 186 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)), 187 | * | withdrawal.shouldUnwrapNativeToken() 188 | | ); 189 | | } 190 | | 191 | * | function remove(DataStore dataStore, bytes32 key, address account) internal { 192 | * | if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) { 193 | * | revert Errors.WithdrawalNotFound(key); 194 | | } 195 | | 196 | * | dataStore.removeBytes32( 197 | | Keys.WITHDRAWAL_LIST, 198 | * | key 199 | | ); 200 | | 201 | * | dataStore.removeBytes32( 202 | * | Keys.accountWithdrawalListKey(account), 203 | * | key 204 | | ); 205 | | 206 | * | dataStore.removeAddress( 207 | * | keccak256(abi.encode(key, ACCOUNT)) 208 | | ); 209 | | 210 | * | dataStore.removeAddress( 211 | * | keccak256(abi.encode(key, RECEIVER)) 212 | | ); 213 | | 214 | * | dataStore.removeAddress( 215 | * | keccak256(abi.encode(key, CALLBACK_CONTRACT)) 216 | | ); 217 | | 218 | * | dataStore.removeAddress( 219 | * | keccak256(abi.encode(key, UI_FEE_RECEIVER)) 220 | | ); 221 | | 222 | * | dataStore.removeAddress( 223 | * | keccak256(abi.encode(key, MARKET)) 224 | | ); 225 | | 226 | * | dataStore.removeAddressArray( 227 | * | keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)) 228 | | ); 229 | | 230 | * | dataStore.removeAddressArray( 231 | * | keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)) 232 | | ); 233 | | 234 | * | dataStore.removeUint( 235 | * | keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)) 236 | | ); 237 | | 238 | * | dataStore.removeUint( 239 | * | keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)) 240 | | ); 241 | | 242 | * | dataStore.removeUint( 243 | * | keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)) 244 | | ); 245 | | 246 | * | dataStore.removeUint( 247 | * | keccak256(abi.encode(key, UPDATED_AT_BLOCK)) 248 | | ); 249 | | 250 | * | dataStore.removeUint( 251 | * | keccak256(abi.encode(key, UPDATED_AT_TIME)) 252 | | ); 253 | | 254 | * | dataStore.removeUint( 255 | * | keccak256(abi.encode(key, EXECUTION_FEE)) 256 | | ); 257 | | 258 | * | dataStore.removeUint( 259 | * | keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)) 260 | | ); 261 | | 262 | * | dataStore.removeBool( 263 | * | keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)) 264 | | ); 265 | | } 266 | | 267 | | function getWithdrawalCount(DataStore dataStore) internal view returns (uint256) { 268 | | return dataStore.getBytes32Count(Keys.WITHDRAWAL_LIST); 269 | | } 270 | | 271 | | function getWithdrawalKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 272 | | return dataStore.getBytes32ValuesAt(Keys.WITHDRAWAL_LIST, start, end); 273 | | } 274 | | 275 | | function getAccountWithdrawalCount(DataStore dataStore, address account) internal view returns (uint256) { 276 | | return dataStore.getBytes32Count(Keys.accountWithdrawalListKey(account)); 277 | | } 278 | | 279 | | function getAccountWithdrawalKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) { 280 | | return dataStore.getBytes32ValuesAt(Keys.accountWithdrawalListKey(account), start, end); 281 | | } 282 | | } 283 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalUtils.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../adl/AdlUtils.sol"; 6 | | 7 | | import "../data/DataStore.sol"; 8 | | 9 | | import "./WithdrawalVault.sol"; 10 | | import "./WithdrawalStoreUtils.sol"; 11 | | import "./WithdrawalEventUtils.sol"; 12 | | 13 | | import "../nonce/NonceUtils.sol"; 14 | | import "../pricing/SwapPricingUtils.sol"; 15 | | import "../oracle/Oracle.sol"; 16 | | import "../oracle/OracleUtils.sol"; 17 | | 18 | | import "../gas/GasUtils.sol"; 19 | | import "../callback/CallbackUtils.sol"; 20 | | 21 | | import "../utils/Array.sol"; 22 | | import "../utils/AccountUtils.sol"; 23 | | 24 | | /** 25 | | * @title WithdrawalUtils 26 | | * @dev Library for withdrawal functions 27 | | */ 28 | * | library WithdrawalUtils { 29 | | using SafeCast for uint256; 30 | | using SafeCast for int256; 31 | | using Array for uint256[]; 32 | | using Price for Price.Props; 33 | | using Withdrawal for Withdrawal.Props; 34 | | 35 | | using EventUtils for EventUtils.AddressItems; 36 | | using EventUtils for EventUtils.UintItems; 37 | | using EventUtils for EventUtils.IntItems; 38 | | using EventUtils for EventUtils.BoolItems; 39 | | using EventUtils for EventUtils.Bytes32Items; 40 | | using EventUtils for EventUtils.BytesItems; 41 | | using EventUtils for EventUtils.StringItems; 42 | | 43 | | enum WithdrawalType { 44 | | Normal, 45 | | Shift, 46 | | Glv 47 | | } 48 | | 49 | | /** 50 | | * @param receiver The address that will receive the withdrawal tokens. 51 | | * @param callbackContract The contract that will be called back. 52 | | * @param market The market on which the withdrawal will be executed. 53 | | * @param minLongTokenAmount The minimum amount of long tokens that must be withdrawn. 54 | | * @param minShortTokenAmount The minimum amount of short tokens that must be withdrawn. 55 | | * @param shouldUnwrapNativeToken Whether the native token should be unwrapped when executing the withdrawal. 56 | | * @param executionFee The execution fee for the withdrawal. 57 | | * @param callbackGasLimit The gas limit for calling the callback contract. 58 | | */ 59 | | struct CreateWithdrawalParams { 60 | | address receiver; 61 | | address callbackContract; 62 | | address uiFeeReceiver; 63 | | address market; 64 | | address[] longTokenSwapPath; 65 | | address[] shortTokenSwapPath; 66 | | uint256 minLongTokenAmount; 67 | | uint256 minShortTokenAmount; 68 | | bool shouldUnwrapNativeToken; 69 | | uint256 executionFee; 70 | | uint256 callbackGasLimit; 71 | | } 72 | | 73 | | /** 74 | | * @dev Creates a withdrawal in the withdrawal store. 75 | | * 76 | | * @param dataStore The data store where withdrawal data is stored. 77 | | * @param eventEmitter The event emitter that is used to emit events. 78 | | * @param withdrawalVault WithdrawalVault. 79 | | * @param account The account that initiated the withdrawal. 80 | | * @param params The parameters for creating the withdrawal. 81 | | * @return The unique identifier of the created withdrawal. 82 | | */ 83 | * | function createWithdrawal( 84 | | DataStore dataStore, 85 | | EventEmitter eventEmitter, 86 | | WithdrawalVault withdrawalVault, 87 | | address account, 88 | | CreateWithdrawalParams memory params 89 | * | ) internal returns (bytes32) { 90 | * | AccountUtils.validateAccount(account); 91 | | 92 | * | address wnt = TokenUtils.wnt(dataStore); 93 | * | uint256 wntAmount = withdrawalVault.recordTransferIn(wnt); 94 | | 95 | * | if (wntAmount < params.executionFee) { 96 | | revert Errors.InsufficientWntAmount(wntAmount, params.executionFee); 97 | | } 98 | | 99 | * | AccountUtils.validateReceiver(params.receiver); 100 | | 101 | * | uint256 marketTokenAmount = withdrawalVault.recordTransferIn(params.market); 102 | | 103 | * | if (marketTokenAmount == 0) { 104 | * | revert Errors.EmptyWithdrawalAmount(); 105 | | } 106 | | 107 | * | params.executionFee = wntAmount; 108 | | 109 | * | MarketUtils.validateEnabledMarket(dataStore, params.market); 110 | * | MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath); 111 | * | MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath); 112 | | 113 | * | Withdrawal.Props memory withdrawal = Withdrawal.Props( 114 | * | Withdrawal.Addresses( 115 | * | account, 116 | * | params.receiver, 117 | * | params.callbackContract, 118 | * | params.uiFeeReceiver, 119 | * | params.market, 120 | * | params.longTokenSwapPath, 121 | * | params.shortTokenSwapPath 122 | | ), 123 | * | Withdrawal.Numbers( 124 | * | marketTokenAmount, 125 | * | params.minLongTokenAmount, 126 | * | params.minShortTokenAmount, 127 | * | Chain.currentBlockNumber(), 128 | * | Chain.currentTimestamp(), 129 | * | params.executionFee, 130 | * | params.callbackGasLimit 131 | | ), 132 | * | Withdrawal.Flags( 133 | * | params.shouldUnwrapNativeToken 134 | | ) 135 | | ); 136 | | 137 | * | CallbackUtils.validateCallbackGasLimit(dataStore, withdrawal.callbackGasLimit()); 138 | | 139 | * | uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal); 140 | * | uint256 oraclePriceCount = GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length); 141 | * | GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee, oraclePriceCount); 142 | | 143 | * | bytes32 key = NonceUtils.getNextKey(dataStore); 144 | | 145 | * | WithdrawalStoreUtils.set(dataStore, key, withdrawal); 146 | | 147 | * | WithdrawalEventUtils.emitWithdrawalCreated(eventEmitter, key, withdrawal, WithdrawalType.Normal); 148 | | 149 | * | return key; 150 | | } 151 | | 152 | | /** 153 | | * @dev Cancels a withdrawal. 154 | | * @param dataStore The data store. 155 | | * @param eventEmitter The event emitter. 156 | | * @param withdrawalVault The withdrawal vault. 157 | | * @param key The withdrawal key. 158 | | * @param keeper The keeper sending the transaction. 159 | | * @param startingGas The starting gas for the transaction. 160 | | */ 161 | * | function cancelWithdrawal( 162 | | DataStore dataStore, 163 | | EventEmitter eventEmitter, 164 | | WithdrawalVault withdrawalVault, 165 | | bytes32 key, 166 | | address keeper, 167 | | uint256 startingGas, 168 | | string memory reason, 169 | | bytes memory reasonBytes 170 | * | ) internal { 171 | | // 63/64 gas is forwarded to internal calls, reduce the startingGas to account for this 172 | * | startingGas -= gasleft() / 63; 173 | | 174 | * | Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key); 175 | | 176 | * | if (withdrawal.account() == address(0)) { 177 | * | revert Errors.EmptyWithdrawal(); 178 | | } 179 | | 180 | * | if (withdrawal.marketTokenAmount() == 0) { 181 | | revert Errors.EmptyWithdrawalAmount(); 182 | | } 183 | | 184 | * | WithdrawalStoreUtils.remove(dataStore, key, withdrawal.account()); 185 | | 186 | * | withdrawalVault.transferOut( 187 | * | withdrawal.market(), 188 | * | withdrawal.account(), 189 | * | withdrawal.marketTokenAmount(), 190 | * | false // shouldUnwrapNativeToken 191 | | ); 192 | | 193 | * | WithdrawalEventUtils.emitWithdrawalCancelled( 194 | * | eventEmitter, 195 | * | key, 196 | * | withdrawal.account(), 197 | * | reason, 198 | * | reasonBytes 199 | | ); 200 | | 201 | * | EventUtils.EventLogData memory eventData; 202 | * | CallbackUtils.afterWithdrawalCancellation(key, withdrawal, eventData); 203 | | 204 | * | GasUtils.payExecutionFee( 205 | * | dataStore, 206 | * | eventEmitter, 207 | * | withdrawalVault, 208 | * | key, 209 | * | withdrawal.callbackContract(), 210 | * | withdrawal.executionFee(), 211 | * | startingGas, 212 | * | GasUtils.estimateWithdrawalOraclePriceCount(withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length), 213 | * | keeper, 214 | * | withdrawal.receiver() 215 | | ); 216 | | } 217 | | } 218 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/contracts/withdrawal/WithdrawalVault.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../bank/StrictBank.sol"; 6 | | 7 | | // @title WithdrawalVault 8 | | // @dev Vault for withdrawals 9 | * | contract WithdrawalVault is StrictBank { 10 | | constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {} 11 | | } 12 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/FuzzEchidna.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./helpers/GMXSetup.sol"; 6 | | 7 | *r | contract FuzzEchidna is GMXSetup { 8 | | constructor() payable { 9 | | SetUpGMX(); 10 | | } 11 | | 12 | | receive() external payable {} 13 | | } 14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/config/FuzzConfig.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../setup/FuzzSetup.sol"; 6 | | 7 | | contract FuzzConfig is FuzzSetup { 8 | | //GMX CONFIG 9 | * | uint256 constant DECREASE_POSITION_DELTA_MIN = 1e30; 10 | * | uint256 constant RANDOMIZER_DIVISOR = 4545242; 11 | * | uint256 constant DECREASE_POSITION_TOLERABLE_PRICE_SUB = 1e10; //FROM 1e30 12 | | 13 | * | uint256 constant WETH_MIN_PRICE = 1000e4; 14 | * | uint256 constant WBTC_MIN_PRICE = 1000e2; 15 | * | uint256 constant USDT_MIN_PRICE = 1e6; 16 | * | uint256 constant USDC_MIN_PRICE = 1e6; 17 | * | uint256 constant SOL_MIN_PRICE = 1e4; 18 | | 19 | * | uint256 constant WETH_MAX_PRICE = 1_000_000e4; 20 | * | uint256 constant WBTC_MAX_PRICE = 1_000_000e2; 21 | * | uint256 constant USDT_MAX_PRICE = 1e6; 22 | * | uint256 constant USDC_MAX_PRICE = 1e6; 23 | * | uint256 constant SOL_MAX_PRICE = 1_000_000e4; 24 | | 25 | | //uint256 constant WETH_MAX_AMOUNT is a balance of native ETH or user 26 | * | uint256 constant WBTC_MAX_AMOUNT = 15_000e8; 27 | * | uint256 constant USDT_MAX_AMOUNT = 1000_000_000e6; 28 | * | uint256 constant USDC_MAX_AMOUNT = 1000_000_000e6; 29 | * | uint256 constant SOL_MAX_AMOUNT = 1000000e9; 30 | | 31 | * | uint256 constant WETH_MIN_AMOUNT = 1e16; 32 | * | uint256 constant WBTC_MIN_AMOUNT = 1e6; 33 | * | uint256 constant USDT_MIN_AMOUNT = 1e6; 34 | * | uint256 constant USDC_MIN_AMOUNT = 1e6; 35 | * | uint256 constant SOL_MIN_AMOUNT = 1e8; 36 | | 37 | * | uint256 constant FIXED_EXECUTION_FEE_AMOUNT = 1e10; 38 | * | bool constant SWAPS_ENABLED = false; 39 | | uint constant MIN_AMOUNT_TO_SHIFT = 1e16; 40 | | } 41 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/ADLSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./PropertiesSetup.sol"; 6 | | 7 | | contract ADLSetup is PropertiesSetup { 8 | | struct ADL_cache { 9 | | bytes callData_SwitchADL; 10 | | bool success_SwitchADL; 11 | | bytes returnData_SwitchADL; 12 | | bytes callData_ExecuteADL; 13 | | bool success_ExecuteADL; 14 | | bytes returnData_ExecuteADL; 15 | | bytes callData_SwitchADL_back; 16 | | bool success_SwitchADL_back; 17 | | bytes returnData_SwitchADL_back; 18 | | } 19 | * | function ExecuteADLonVault(uint8 userIndex, uint seed) public { 20 | * | (, , , address user) = _gamma_getVault(userIndex); //gmxUtils is a holder of position 21 | | 22 | * | Position.Props[] memory positions = reader.getAccountPositions( 23 | * | dataStore, 24 | * | user, 25 | * | 0, 26 | * | 10 27 | | ); 28 | * | Position.Props memory positionToADL = positions[0]; 29 | | 30 | * | bytes32 positionKey = Position.getPositionKey( 31 | * | user, 32 | * | positionToADL.addresses.market, 33 | * | positionToADL.addresses.collateralToken, 34 | * | positionToADL.flags.isLong 35 | | ); 36 | | 37 | * | Market.Props memory marketProps = MarketStoreUtils.get( 38 | * | dataStore, 39 | * | positionToADL.addresses.market 40 | | ); 41 | | 42 | * | TokenPrices memory tokenPrices = _setTokenPrices( 43 | * | seed //priceseed for the max price 44 | | ); 45 | | 46 | * | ReaderUtils.PositionInfo memory positionInfo = reader.getPositionInfo( 47 | * | dataStore, 48 | * | referralStorage, 49 | * | positionKey, 50 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 51 | * | 0, //size delta usd == 0 because usePositionSizeAsSizeDeltaUsd is true 52 | * | address(0), //uiFeeReceiver 53 | * | true //usePositionSizeAsSizeDeltaUsd 54 | | ); 55 | | 56 | * | uint reduceSizeBy = clampBetween( 57 | * | seed, 58 | * | 1, 59 | * | positionInfo.position.numbers.sizeInUsd 60 | | ); 61 | | 62 | * | _adl( 63 | * | marketProps, 64 | * | user, 65 | * | positionToADL.addresses.market, 66 | * | positionToADL.flags.isLong, 67 | * | positionToADL.addresses.collateralToken, 68 | * | reduceSizeBy, 69 | * | tokenPrices 70 | | ); 71 | | 72 | * | ReaderUtils.PositionInfo memory positionInfoAfter = reader 73 | | .getPositionInfo( 74 | * | dataStore, 75 | * | referralStorage, 76 | * | positionKey, 77 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 78 | * | 0, //size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true 79 | * | address(0), 80 | * | true //usePositionSizeAsSizeDeltaUsd 81 | | ); 82 | | 83 | * | invariantPositionSizeUSDShouldDecrease( 84 | * | positionInfo.position.numbers.sizeInUsd, 85 | * | positionInfoAfter.position.numbers.sizeInUsd, 86 | * | reduceSizeBy 87 | | ); 88 | | } 89 | | 90 | * | function ExecuteADL(uint8 userIndex, uint seed) public { 91 | * | address user = _getRandomUser(userIndex); 92 | | 93 | * | Position.Props[] memory positions = reader.getAccountPositions( 94 | * | dataStore, 95 | * | user, 96 | * | 0, 97 | * | 10 98 | | ); 99 | * | Position.Props memory positionToADL = positions[0]; 100 | | 101 | * | bytes32 positionKey = Position.getPositionKey( 102 | * | user, 103 | * | positionToADL.addresses.market, 104 | * | positionToADL.addresses.collateralToken, 105 | * | positionToADL.flags.isLong 106 | | ); 107 | | 108 | * | Market.Props memory marketProps = MarketStoreUtils.get( 109 | * | dataStore, 110 | * | positionToADL.addresses.market 111 | | ); 112 | | 113 | * | TokenPrices memory tokenPrices = _setTokenPrices( 114 | * | seed //priceseed for the max price 115 | | ); 116 | | 117 | * | ReaderUtils.PositionInfo memory positionInfo = reader.getPositionInfo( 118 | * | dataStore, 119 | * | referralStorage, 120 | * | positionKey, 121 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 122 | * | 0, //size delta usd == 0 because usePositionSizeAsSizeDeltaUsd is true 123 | * | address(0), //uiFeeReceiver 124 | * | true //usePositionSizeAsSizeDeltaUsd 125 | | ); 126 | | 127 | * | uint reduceSizeBy = clampBetween( 128 | * | seed, 129 | * | 1, 130 | * | positionInfo.position.numbers.sizeInUsd 131 | | ); 132 | | 133 | * | _adl( 134 | * | marketProps, 135 | * | user, 136 | * | positionToADL.addresses.market, 137 | * | positionToADL.flags.isLong, 138 | * | positionToADL.addresses.collateralToken, 139 | * | reduceSizeBy, 140 | * | tokenPrices 141 | | ); 142 | | 143 | * | ReaderUtils.PositionInfo memory positionInfoAfter = reader 144 | | .getPositionInfo( 145 | * | dataStore, 146 | * | referralStorage, 147 | * | positionKey, 148 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 149 | * | 0, //size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true 150 | * | address(0), 151 | * | true //usePositionSizeAsSizeDeltaUsd 152 | | ); 153 | | 154 | * | invariantPositionSizeUSDShouldDecrease( 155 | * | positionInfo.position.numbers.sizeInUsd, 156 | * | positionInfoAfter.position.numbers.sizeInUsd, 157 | * | reduceSizeBy 158 | | ); 159 | | } 160 | | 161 | * | function _adl( 162 | | Market.Props memory marketProps, 163 | | address user, 164 | | address market, 165 | | bool isLong, 166 | | address collateralToken, 167 | | uint reduceSizeBy, 168 | | TokenPrices memory tokenPrices 169 | * | ) internal { 170 | * | ADL_cache memory cache; 171 | | 172 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 173 | * | tokenPrices.tokens, 174 | * | tokenPrices.maxPrices, 175 | * | tokenPrices.minPrices 176 | | ); 177 | | 178 | * | cache.callData_SwitchADL = abi.encodeWithSelector( 179 | * | adlHandler.updateAdlState.selector, 180 | * | market, 181 | * | isLong, 182 | * | oracleParams 183 | | ); 184 | | 185 | * | vm.prank(DEPLOYER); 186 | * | adlHandler.updateAdlState(market, isLong, oracleParams); 187 | | 188 | * | vm.prank(DEPLOYER); 189 | *r | adlHandler.executeAdl( 190 | * | user, 191 | * | market, 192 | * | collateralToken, 193 | * | isLong, 194 | * | reduceSizeBy, 195 | * | oracleParams 196 | | ); 197 | | 198 | | //Switching prices back to minimum and disabling ADL 199 | * | TokenPrices memory lowestTokenPrices = _setTokenPrices(1000e4); 200 | | 201 | * | OracleUtils.SetPricesParams 202 | * | memory oracleParamsSwitchADL = SetOraclePrices( 203 | * | lowestTokenPrices.tokens, 204 | * | lowestTokenPrices.maxPrices, 205 | * | lowestTokenPrices.minPrices 206 | | ); 207 | | 208 | * | vm.prank(DEPLOYER); 209 | * | adlHandler.updateAdlState(market, isLong, oracleParams); 210 | * | bool isAdlEnabled = dataStore.getBool( 211 | * | Keys.isAdlEnabledKey(market, isLong) 212 | | ); 213 | | 214 | * | require(!isAdlEnabled, "ADL should be disabled"); 215 | | } 216 | | } 217 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/BaseSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "../config/FuzzConfig.sol"; 5 | | import "../interfaces/IMockDex.sol"; 6 | | 7 | | contract BaseSetup is FuzzConfig { 8 | | mapping(address => uint256) internal tokenMinAmounts; 9 | | mapping(address => uint256) internal tokenMaxAmounts; 10 | | mapping(address => uint256) internal tokenMinPrice; 11 | | mapping(address => uint256) internal tokenMaxPrice; 12 | | 13 | | /** 14 | | .-", 15 | | `~ || 16 | | ||___ GAMMA Structs 17 | | (':.)` 18 | | || || 19 | | || || 20 | | ^^ ^^ 21 | | */ 22 | | struct DepositInfo { 23 | | uint256 amount; 24 | | uint256 shares; 25 | | address owner; 26 | | uint256 timestamp; 27 | | address recipient; 28 | | } 29 | | enum PROTOCOL { 30 | | DEX, 31 | | GMX 32 | | } 33 | | 34 | | struct SwapProgress { 35 | | // swap process involves asynchronous operation so store swap progress data 36 | | bool isCollateralToIndex; // if swap `collateralToken` to `indexToken`, true and vice versa. 37 | | uint256 swapped; // the amount of output token that has already been swapped. 38 | | uint256 remaining; // the amount of input token that remains to be swapped 39 | | } 40 | | 41 | | enum NextActionSelector { 42 | | NO_ACTION, // state where no action is required 43 | | INCREASE_ACTION, // represents increasing actions such as increasing a GMX perps position or increasing a spot position 44 | | SWAP_ACTION, // represents swapping a token, either collateral to index or vice versa 45 | | WITHDRAW_ACTION, // represents withdrawing funds 46 | | COMPOUND_ACTION, // whenver claiming positive funding fee, we could have idle funds in the vault. 47 | | // If it's enough to deposit more into GMX, triggers `COMPOUND_ACTION`. 48 | | SETTLE_ACTION, // settle fees and ensure state is up-to-date prior to withdrawals 49 | | FINALIZE 50 | | } 51 | | 52 | | enum FLOW { 53 | | NONE, 54 | | DEPOSIT, 55 | | SIGNAL_CHANGE, 56 | | WITHDRAW, 57 | | COMPOUND 58 | | } 59 | | 60 | | struct UserState { 61 | | uint USDCBalance; 62 | | uint256 totalAmount; 63 | | uint256 totalShares; 64 | | uint256[] depositIds; 65 | | mapping(uint256 => uint) deposits; //depositID => deposit amount 66 | | uint256 lastDepositTimestamp; 67 | | uint256 shareValue; 68 | | } 69 | | struct Action { 70 | | NextActionSelector selector; 71 | | bytes data; 72 | | } 73 | | struct VaultInfo { 74 | | mapping(address => UserState) userStates; 75 | | uint256 totalAmount; 76 | | uint256 vaultUSDCBalance; 77 | | uint256 totalSharesCalculated; 78 | | uint256 oldestDepositTimestamp; 79 | | uint256 newestDepositTimestamp; 80 | | uint256 totalShares; 81 | | uint256 counter; 82 | | bytes32 curPositionKey; 83 | | uint256 totalDepositAmount; 84 | | bool beenLong; 85 | | bool positionIsClosed; 86 | | bool gmxLock; 87 | | bool isBusy; 88 | | bool isLocked; 89 | | NextActionSelector nextActionSelector; 90 | | uint treasuryBalance; 91 | | uint256 shareValue; 92 | | uint256 totalFees; 93 | | uint256 collateralAmount; 94 | | } 95 | | struct State { 96 | | mapping(address => VaultInfo) vaultInfos; 97 | | } 98 | | 99 | | mapping(uint8 => State) internal states; 100 | | 101 | | struct gammaWithdrawal { 102 | | address user; 103 | | address vault; 104 | | uint256 depositId; 105 | | } 106 | | 107 | | gammaWithdrawal internal withdrawalAssertionInputs; 108 | | 109 | | /** 110 | | .-", 111 | | `~ || 112 | | ||___ DEPOSIT Structs 113 | | (':.)` 114 | | || || 115 | | || || 116 | | ^^ ^^ 117 | | */ 118 | | 119 | | struct DepositorParams { 120 | | address user; 121 | | uint256 longAmount; 122 | | uint256 shortAmount; 123 | | bool isWETH; 124 | | } 125 | | 126 | | struct DepositParams { 127 | | address receiver; 128 | | address callbackContract; 129 | | address uiFeeReceiver; 130 | | address[] longTokenSwapPath; 131 | | address[] shortTokenSwapPath; 132 | | uint256 minMarketTokens; 133 | | bool shouldUnwrapNativeToken; 134 | | uint256 executionFee; 135 | | uint256 callbackGasLimit; 136 | | } 137 | | 138 | | struct DepositCreated { 139 | | DepositState beforeDepositExec; 140 | | DepositParams depositParams; 141 | | DepositorParams depositorParams; 142 | | DepositUtils.CreateDepositParams createDepositParams; 143 | | address[] longSwapPath; 144 | | address[] shortSwapPath; 145 | | bytes32 key; 146 | | TokenPrices tokenPrices; 147 | | } 148 | | 149 | | struct DepositState { 150 | | address market; 151 | | address user; 152 | | uint marketTotalSupply; 153 | | uint userBalanceMarket; 154 | | uint userBalanceLong; 155 | | uint userBalanceShort; 156 | | uint vaultBalanceLong; 157 | | uint vaultBalanceShort; 158 | | uint simulateDepositAmountOut; 159 | | uint longAmountFromParams; 160 | | uint shortAmountFromParams; 161 | | } 162 | | 163 | | /** 164 | | .-", 165 | | `~ || 166 | | ||___ SHIFT Structs 167 | | (':.)` 168 | | || || 169 | | || || 170 | | ^^ ^^ 171 | | */ 172 | | 173 | | struct ShiftCreated { 174 | | ShiftState beforeExec; 175 | | ShiftUtils.CreateShiftParams createShiftParams; 176 | | uint marketTokenAmount; 177 | | bytes32 key; 178 | | } 179 | | 180 | | struct ShiftMarketData { 181 | | int marketTokenPriceFrom; 182 | | int marketTokenPriceTo; 183 | | uint simulateLongTokenAmountWithdrawal; 184 | | uint simulateShortTokenAmountWithdrawal; 185 | | } 186 | | 187 | | struct ShiftState { 188 | | ShiftUtils.CreateShiftParams createShiftParams; 189 | | ShiftMarketData marketDataBefore; 190 | | ShiftMarketData marketDataAfter; 191 | | uint marketTokenAmount; 192 | | TokenPrices tokenPrices; 193 | | address user; 194 | | uint marketFromBalance; 195 | | uint marketToBalance; 196 | | uint longTokenPoolAmountMarketFrom; 197 | | uint shortTokenPoolAmountMarketFrom; 198 | | uint longTokenPoolAmountMarketTo; 199 | | uint shortTokenPoolAmountMarketTo; 200 | | uint longTokenMarketFeeAmountMarketFrom; 201 | | uint shortTokenMarketFeeAmountMarketFrom; 202 | | } 203 | | 204 | | /** 205 | | .-", 206 | | `~ || 207 | | ||___ POSITION Structs 208 | | (':.)` 209 | | || || 210 | | || || 211 | | ^^ ^^ 212 | | */ 213 | | 214 | | struct OrderCreated { 215 | | IBaseOrderUtils.CreateOrderParams createOrderParams; 216 | | bytes32 key; 217 | | uint256 updatedAt; 218 | | address user; 219 | | bytes32 handlerType; 220 | | uint amountSent; 221 | | bool isClose; 222 | | uint8 swapPathSeed; 223 | | TokenPrices tokenPrices; 224 | | uint executionFee; 225 | | } 226 | | 227 | | struct PositionState { 228 | | uint sizeInUsd; 229 | | uint sizeInTokens; 230 | | uint collateralAmount; 231 | | bool isLong; 232 | | uint OILong; 233 | | uint OILongLatestMarket; 234 | | uint OIShort; 235 | | uint collateralSumLong; 236 | | uint collateralSumShort; 237 | | uint balanceOfLongToken; 238 | | uint balanceOfShortToken; 239 | | } 240 | | 241 | | struct SwapState { 242 | | uint balanceOfOutputToken; 243 | | uint balanceOfInputToken; 244 | | address outputToken; 245 | | SwapResult swapResult; 246 | | } 247 | | 248 | | struct SwapResult { 249 | | uint256 amountOut; 250 | | uint256 amountAfterFees; 251 | | int256 totalImpactAmount; 252 | | SwapPricingUtils.SwapFees totalFees; 253 | | } 254 | | 255 | | struct GetAmountsOutCache { 256 | | Market.Props market; 257 | | MarketUtils.MarketPrices prices; 258 | | address currentToken; 259 | | uint currentAmount; 260 | | address uiFeeReceiver; 261 | | } 262 | | /** 263 | | .-", 264 | | `~ || 265 | | ||___ WITHDRAWAL Structs 266 | | (':.)` 267 | | || || 268 | | || || 269 | | ^^ ^^ 270 | | */ 271 | | 272 | | struct WithdrawalCreated { 273 | | WithdrawalUtils.CreateWithdrawalParams withdrawalParams; 274 | | uint amount; 275 | | bytes32 withdrawalKey; 276 | | } 277 | | 278 | | struct WithdrawalState { 279 | | uint userBalance; 280 | | uint vaultBalance; 281 | | uint marketTokenTotalSupply; 282 | | uint longTokenBalanceMarketVault; 283 | | uint shortTokenBalanceMarketVault; 284 | | uint longTokenBalanceUser; 285 | | uint shortTokenBalanceUser; 286 | | uint simulateLongTokenAmountWithdrawal; 287 | | uint simulateShortTokenAmountWithdrawal; 288 | | uint nativeTokenBalanceUser; 289 | | } 290 | | 291 | | struct MarketData { 292 | | Market.Props marketFromProps; 293 | | Market.Props marketToProps; 294 | | Market.Props marketToUpdate; 295 | | } 296 | | 297 | | struct TokenPrices { 298 | | address[] tokens; 299 | | uint[] maxPrices; 300 | | uint[] minPrices; 301 | | } 302 | | 303 | | // GAMMA Fuzzing helpers 304 | | 305 | | function _logFlow(address vault) internal { 306 | | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow(); 307 | | uint flowValue = uint(currentFlow); 308 | | 309 | | if (flowValue == 0) { 310 | | fl.log("EXECUTE ORDER: FLOW NONE"); 311 | | } else if (flowValue == 1) { 312 | | fl.log("EXECUTE ORDER: DEPOSIT"); 313 | | } else if (flowValue == 2) { 314 | | fl.log("EXECUTE ORDER: SIGNAL_CHANGE"); 315 | | } else if (flowValue == 3) { 316 | | fl.log("EXECUTE ORDER: WITHDRAW"); 317 | | } else if (flowValue == 4) { 318 | | fl.log("EXECUTE ORDER: COMPOUND"); 319 | | } else { 320 | | fl.log("EXECUTE ORDER: UNKNOWN FLOW"); 321 | | } 322 | | } 323 | * | function logNextAction(address vault) internal { 324 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 325 | | 326 | * | ( 327 | * | PerpetualVault.NextActionSelector selector, 328 | * | bytes memory data 329 | * | ) = perpetualVault.nextAction(); 330 | | 331 | * | if (selector == PerpetualVault.NextActionSelector.NO_ACTION) { 332 | * | fl.log("Next action is NO_ACTION"); 333 | * | } else if ( 334 | * | selector == PerpetualVault.NextActionSelector.INCREASE_ACTION 335 | | ) { 336 | * | fl.log("Next action is INCREASE_ACTION"); 337 | * | } else if (selector == PerpetualVault.NextActionSelector.SWAP_ACTION) { 338 | * | fl.log("Next action is SWAP_ACTION"); 339 | * | } else if ( 340 | * | selector == PerpetualVault.NextActionSelector.WITHDRAW_ACTION 341 | | ) { 342 | * | fl.log("Next action is WITHDRAW_ACTION"); 343 | * | } else if ( 344 | * | selector == PerpetualVault.NextActionSelector.COMPOUND_ACTION 345 | | ) { 346 | | fl.log("Next action is COMPOUND_ACTION"); 347 | * | } else if ( 348 | * | selector == PerpetualVault.NextActionSelector.SETTLE_ACTION 349 | | ) { 350 | * | fl.log("Next action is SETTLE_ACTION"); 351 | * | } else if (selector == PerpetualVault.NextActionSelector.FINALIZE) { 352 | * | fl.log("Next action is FINALIZE"); 353 | | } else { 354 | | fl.log("Unknown next action"); 355 | | } 356 | | } 357 | | 358 | * | function _gamma_getVault( 359 | | uint8 seed 360 | * | ) internal returns (address, uint, address, address) { 361 | * | uint256 vaultIndex = seed % 6; 362 | * | if (vaultIndex == 0) { 363 | * | return ( 364 | * | vault_GammaVault1x_WETHUSDC, 365 | * | 1, 366 | * | market_WETH_WETH_USDC, 367 | * | gmxUtils_GammaVault1x_WETHUSDC 368 | | ); 369 | * | } else if (vaultIndex == 1) { 370 | * | return ( 371 | * | vault_GammaVault2x_WETHUSDC, 372 | * | 2, 373 | * | market_WETH_WETH_USDC, 374 | * | gmxUtils_GammaVault2x_WETHUSDC 375 | | ); 376 | * | } else if (vaultIndex == 2) { 377 | * | return ( 378 | * | vault_GammaVault3x_WETHUSDC, 379 | * | 3, 380 | * | market_WETH_WETH_USDC, 381 | * | gmxUtils_GammaVault3x_WETHUSDC 382 | | ); 383 | * | } else if (vaultIndex == 3) { 384 | * | return ( 385 | * | vault_GammaVault1x_WBTCUSDC, 386 | * | 1, 387 | * | market_WBTC_WBTC_USDC, 388 | * | gmxUtils_GammaVault1x_WBTCUSDC 389 | | ); 390 | * | } else if (vaultIndex == 4) { 391 | * | return ( 392 | * | vault_GammaVault2x_WBTCUSDC, 393 | * | 2, 394 | * | market_WBTC_WBTC_USDC, 395 | * | gmxUtils_GammaVault2x_WBTCUSDC 396 | | ); 397 | | } else { 398 | * | return ( 399 | * | vault_GammaVault3x_WBTCUSDC, 400 | * | 3, 401 | * | market_WBTC_WBTC_USDC, 402 | * | gmxUtils_GammaVault3x_WBTCUSDC 403 | | ); 404 | | } 405 | | } 406 | * | function getConvertedMarketPrices( 407 | | address market, 408 | | uint256 priceSeed 409 | * | ) internal returns (MarketPrices memory) { 410 | * | MarketUtils.MarketPrices memory prices = _getMarketPrices( 411 | * | market, 412 | * | _setTokenPrices(priceSeed) 413 | | ); 414 | | 415 | * | MarketPrices memory convertedPrices = MarketPrices({ 416 | * | indexTokenPrice: PriceProps({ 417 | * | min: prices.indexTokenPrice.min, 418 | * | max: prices.indexTokenPrice.max 419 | | }), 420 | * | longTokenPrice: PriceProps({ 421 | * | min: prices.longTokenPrice.min, 422 | * | max: prices.longTokenPrice.max 423 | | }), 424 | * | shortTokenPrice: PriceProps({ 425 | * | min: prices.shortTokenPrice.min, 426 | * | max: prices.shortTokenPrice.max 427 | | }) 428 | | }); 429 | | 430 | * | return convertedPrices; 431 | | } 432 | * | function _getRandomDepositId( 433 | | uint8 seed, 434 | | address user, 435 | | address vault 436 | * | ) internal view returns (uint256) { 437 | * | uint256[] memory depositIds = PerpetualVault(vault).getUserDeposits( 438 | * | user 439 | | ); 440 | | 441 | *r | require(depositIds.length > 0, "No deposits found for the user"); 442 | | 443 | * | if (depositIds.length == 1) { 444 | * | return depositIds[0]; 445 | | } 446 | | 447 | * | uint256 randomIndex = seed % depositIds.length; 448 | * | return depositIds[randomIndex]; 449 | | } 450 | | 451 | *r | function constructSwapCalldata( 452 | | address tokenIn, 453 | | address tokenOut, 454 | | uint256 amountIn, 455 | | uint256 amountOutMin, 456 | | address vault 457 | * | ) public returns (bytes memory) { 458 | | // Allocate memory for swapCalldata (4 + 7 * 32 = 228 bytes) 459 | * | bytes memory swapCalldata = new bytes(228); 460 | * | bytes4 selector = 0x89fe039b; 461 | | 462 | * | assembly { 463 | | // Get the pointer to the free memory 464 | * | let ptr := add(swapCalldata, 32) 465 | | // Store the function selector in the first 4 bytes 466 | * | mstore(ptr, selector) 467 | | // Store tokenIn 468 | * | mstore(add(ptr, 4), tokenIn) //from token 469 | | // Store tokenOut 470 | * | mstore(add(ptr, 36), tokenOut) //to token 471 | | // Store amountIn 472 | * | mstore(add(ptr, 68), amountIn) 473 | | // Store amountOutMin 474 | * | mstore(add(ptr, 100), amountOutMin) 475 | | // Store placeholder address(0) 476 | * | mstore(add(ptr, 132), 0) 477 | | // Store placeholder address(0) 478 | * | mstore(add(ptr, 164), vault) //to 196 479 | | } 480 | | 481 | | // Construct the data for _doDexSwap 482 | * | bytes memory dexSwapData = abi.encode( 483 | * | PARASWAP_ROUTER, 484 | * | amountIn, 485 | * | swapCalldata 486 | | ); 487 | | 488 | | // Construct the final calldata for _runSwap 489 | * | bytes memory finalCalldata = abi.encode(PROTOCOL.DEX, dexSwapData); 490 | | 491 | * | address valueAt196; 492 | | assembly { 493 | * | valueAt196 := mload(add(swapCalldata, 196)) 494 | | } 495 | | 496 | * | return finalCalldata; 497 | | } 498 | | 499 | * | function constructGMXCalldata( 500 | | uint8 seed, 501 | | uint256 amountIn 502 | * | ) internal returns (bytes memory finalCalldata) { 503 | * | address[] memory gmxpath = _getSwapPath(seed); 504 | * | bytes memory dexSwapData = abi.encode(gmxpath, amountIn, 0); //min output amount hardcoded at 0 505 | * | finalCalldata = abi.encode(PROTOCOL.GMX, dexSwapData); 506 | | } 507 | | 508 | *r | function getPositionCollateral( 509 | | address vault 510 | * | ) public returns (uint collateralAmount) { 511 | *r | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 512 | * | ReaderUtils.PositionInfo memory positionInfo = reader 513 | | .getPositionInfo( 514 | * | dataStore, 515 | * | referralStorage, 516 | * | PerpetualVault(vault).curPositionKey(), 517 | * | _getMarketPrices( 518 | * | vaultToMarket[vault], 519 | * | _setTokenPrices(5000e4) 520 | | ), //any price, checking for collateral 521 | * | uint256(0), 522 | * | address(0), 523 | * | true 524 | | ); 525 | | 526 | * | collateralAmount = positionInfo.position.numbers.collateralAmount; 527 | | } 528 | | } 529 | | 530 | * | function checkNextAction(address vault) public view returns (bool isLong) { 531 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 532 | | 533 | *r | (, bytes memory data) = perpetualVault.nextAction(); 534 | | 535 | * | (isLong, ) = abi.decode(data, (bool, uint256)); 536 | | } 537 | | 538 | * | function isNextNoAction( 539 | | address vault 540 | * | ) public view returns (bool isNoAction) { 541 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 542 | | 543 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault 544 | | .nextAction(); 545 | | 546 | * | if (selector == PerpetualVault.NextActionSelector.NO_ACTION) { 547 | * | return true; 548 | | } 549 | * | return false; 550 | | } 551 | | 552 | * | function isNextFinalize( 553 | | address vault 554 | * | ) public view returns (bool isFinalize) { 555 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 556 | | 557 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault 558 | | .nextAction(); 559 | | 560 | * | if (selector == PerpetualVault.NextActionSelector.FINALIZE) { 561 | * | return true; 562 | | } 563 | * | return false; 564 | | } 565 | * | function isNextSettle(address vault) public view returns (bool isSettle) { 566 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 567 | | 568 | * | (PerpetualVault.NextActionSelector selector, ) = perpetualVault 569 | | .nextAction(); 570 | | 571 | * | if (selector == PerpetualVault.NextActionSelector.SETTLE_ACTION) { 572 | * | return true; 573 | | } 574 | * | return false; 575 | | } 576 | | 577 | * | function isNextWithdraw( 578 | | address vault 579 | * | ) public view returns (bool isFinalize) { 580 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 581 | | 582 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault 583 | | .nextAction(); 584 | | 585 | * | if (selector == PerpetualVault.NextActionSelector.WITHDRAW_ACTION) { 586 | * | return true; 587 | | } 588 | * | return false; 589 | | } 590 | * | function isNextSwap(address vault) public view returns (bool isSwap) { 591 | * | PerpetualVault perpetualVault = PerpetualVault(vault); 592 | | 593 | *r | (PerpetualVault.NextActionSelector selector, ) = perpetualVault 594 | | .nextAction(); 595 | | 596 | * | if (selector == PerpetualVault.NextActionSelector.SWAP_ACTION) { 597 | * | return true; 598 | | } 599 | * | return false; 600 | | } 601 | | // GMX Fuzzing helpers 602 | | 603 | | // Percentage diff inspired by EBTC suite 604 | | //https://github.com/ebtc-protocol/ebtc/blob/3406f0d88ac9935da53f7371fb078d11c066802e/packages/contracts/contracts/TestContracts/invariants/Asserts.sol#L31 605 | * | function eqPercentageDiff( 606 | | uint256 a, 607 | | uint256 b, 608 | | uint256 maxPercentDiff, 609 | | string memory reason 610 | * | ) internal { 611 | * | uint256 percentDiff; 612 | | 613 | * | if (a == b) return; 614 | | 615 | * | if (a > b) { 616 | * | percentDiff = ((a - b) * 1e30) / ((a + b) / 2); 617 | | } else { 618 | * | percentDiff = ((b - a) * 1e30) / ((a + b) / 2); 619 | | } 620 | | 621 | * | if (percentDiff > maxPercentDiff) { 622 | | fl.log("a>b, a: ", a); 623 | | fl.log("a>b, b:", b); 624 | | fl.log( 625 | | "Percentage difference is bigger than expected", 626 | | percentDiff 627 | | ); 628 | | fl.t(false, reason); 629 | | } else { 630 | * | fl.t(true, "Invariant ok, ckeched for: "); 631 | * | fl.log(reason); 632 | * | fl.log("Percentage difference: ", percentDiff); 633 | | } 634 | | } 635 | | 636 | | //General utils 637 | | 638 | * | function _setTokenPrices( 639 | | uint priceSeed 640 | * | ) internal returns (TokenPrices memory) { 641 | * | address[] memory tokens = new address[](5); 642 | * | uint[] memory maxPrices = new uint[](5); 643 | * | uint[] memory minPrices = new uint[](5); 644 | | 645 | * | tokens[0] = address(WETH); 646 | * | tokens[1] = address(WBTC); 647 | * | tokens[2] = address(USDT); 648 | * | tokens[3] = address(USDC); 649 | * | tokens[4] = address(SOL); 650 | | 651 | * | for (uint i = 0; i < tokens.length; i++) { 652 | * | (minPrices[i], maxPrices[i]) = _getTokenPrices( 653 | * | tokens[i], 654 | * | priceSeed 655 | | ); 656 | | } 657 | | 658 | * | TokenPrices memory tokenPrices = TokenPrices({ 659 | * | tokens: tokens, 660 | * | maxPrices: maxPrices, 661 | * | minPrices: minPrices 662 | | }); 663 | | 664 | * | return tokenPrices; 665 | | } 666 | * | function _getTokenPrices( 667 | | address token, 668 | | uint256 price 669 | * | ) internal returns (uint256 minPrice, uint256 maxPrice) { 670 | * | tokenMinPrice[address(WETH)] = WETH_MIN_PRICE; 671 | * | tokenMinPrice[address(WBTC)] = WBTC_MIN_PRICE; 672 | * | tokenMinPrice[address(USDT)] = USDT_MIN_PRICE; 673 | * | tokenMinPrice[address(USDC)] = USDC_MIN_PRICE; 674 | * | tokenMinPrice[address(SOL)] = SOL_MIN_PRICE; 675 | | 676 | * | tokenMaxPrice[address(WETH)] = WETH_MAX_PRICE; 677 | * | tokenMaxPrice[address(WBTC)] = WBTC_MAX_PRICE; 678 | * | tokenMaxPrice[address(USDT)] = USDT_MAX_PRICE; 679 | * | tokenMaxPrice[address(USDC)] = USDC_MAX_PRICE; 680 | * | tokenMaxPrice[address(SOL)] = SOL_MAX_PRICE; 681 | | 682 | * | minPrice = clampBetween( 683 | * | price, 684 | * | tokenMinPrice[token], 685 | * | tokenMaxPrice[token] 686 | | ); 687 | | 688 | * | maxPrice = clampBetween( 689 | * | price, 690 | * | tokenMinPrice[token], 691 | * | tokenMaxPrice[token] 692 | | ); 693 | | 694 | * | if (minPrice > maxPrice) { 695 | | (minPrice, maxPrice) = (maxPrice, minPrice); 696 | | } 697 | | } 698 | | 699 | * | function _getTokenPrice( 700 | | address token, 701 | | TokenPrices memory tokenPrices 702 | * | ) internal returns (uint) { 703 | | //RETURNS MAX PRICE 704 | * | for (uint i = 0; i < tokenPrices.tokens.length; i++) { 705 | * | if (tokenPrices.tokens[i] == token) { 706 | * | return tokenPrices.maxPrices[i] * (10 ** _getPrecision(token)); 707 | | } 708 | | } 709 | | 710 | | revert("Token was not found"); 711 | | } 712 | | 713 | * | function _getTokenAmounts( 714 | | uint longAmount, 715 | | uint shortAmount, 716 | | address longToken, 717 | | address shortToken, 718 | | address user 719 | * | ) internal returns (uint longAmountClamped, uint shortAmountClamped) { 720 | * | tokenMaxAmounts[address(WETH)] = address(user).balance; 721 | * | tokenMaxAmounts[address(WBTC)] = WBTC_MAX_AMOUNT; 722 | * | tokenMaxAmounts[address(USDT)] = USDT_MAX_AMOUNT; 723 | * | tokenMaxAmounts[address(USDC)] = USDC_MAX_AMOUNT; 724 | * | tokenMaxAmounts[address(SOL)] = SOL_MAX_AMOUNT; 725 | | 726 | * | tokenMinAmounts[address(WETH)] = WETH_MIN_AMOUNT; 727 | * | tokenMinAmounts[address(WBTC)] = WBTC_MIN_AMOUNT; 728 | * | tokenMinAmounts[address(USDT)] = USDT_MIN_AMOUNT; 729 | * | tokenMinAmounts[address(USDC)] = USDC_MIN_AMOUNT; 730 | * | tokenMinAmounts[address(SOL)] = SOL_MIN_AMOUNT; 731 | | 732 | * | longAmountClamped = clampBetween( 733 | * | longAmount, 734 | * | tokenMinAmounts[longToken], 735 | * | tokenMaxAmounts[longToken] 736 | | ); 737 | * | shortAmountClamped = clampBetween( 738 | * | shortAmount, 739 | * | tokenMinAmounts[shortToken], 740 | * | tokenMaxAmounts[shortToken] 741 | | ); 742 | | } 743 | | 744 | | /**Lib functions */ 745 | | 746 | | function _getPoolAmount( 747 | | DataStore dataStore, 748 | | Market.Props memory market, 749 | | address token 750 | | ) internal view returns (uint256) { 751 | | uint256 divisor = getPoolDivisor(market.longToken, market.shortToken); 752 | | return 753 | | dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / 754 | | divisor; 755 | | } 756 | | function getPoolDivisor( 757 | | address longToken, 758 | | address shortToken 759 | | ) internal pure returns (uint256) { 760 | | return longToken == shortToken ? 2 : 1; 761 | | } 762 | | /* 763 | | *HELPERS 764 | | * 765 | | */ 766 | | 767 | | function _getClaimableFeeAmount( 768 | | address market, 769 | | address token 770 | | ) internal returns (uint) { 771 | | bytes32 CLAIMABLE_FEE_AMOUNT = keccak256( 772 | | abi.encode("CLAIMABLE_FEE_AMOUNT") 773 | | ); 774 | | bytes32 key = keccak256( 775 | | abi.encode(CLAIMABLE_FEE_AMOUNT, market, token) 776 | | ); 777 | | uint256 feeAmount = dataStore.getUint(key); 778 | | } 779 | | 780 | * | function _getRandomUser(uint8 input) internal returns (address) { 781 | * | uint256 randomIndex = input % USERS.length; 782 | * | return USERS[randomIndex]; 783 | | } 784 | | 785 | * | function _getMarketAddress(uint8 index) internal view returns (address) { 786 | * | uint256 marketIndex = index % 6; 787 | | 788 | * | if (marketIndex == 0) { 789 | * | return market_WETH_WETH_USDC; 790 | * | } else if (marketIndex == 1) { 791 | * | return market_WETH_WETH_USDT; 792 | * | } else if (marketIndex == 2) { 793 | * | return market_0_WETH_USDC; 794 | | } else { 795 | * | return market_WBTC_WBTC_USDC; 796 | | } 797 | | } 798 | | 799 | * | function _getRandomToken(uint8 index) internal view returns (address) { 800 | * | uint tokenIndex = index % 4; 801 | | 802 | * | if (tokenIndex == 0) { 803 | * | return address(USDC); 804 | * | } else if (tokenIndex == 1) { 805 | * | return address(WBTC); 806 | * | } else if (tokenIndex == 2) { 807 | * | return address(USDT); 808 | | } else { 809 | * | return address(WETH); 810 | | } 811 | | } 812 | | 813 | * | function _getMarketPrices( 814 | | address marketToUpdate, 815 | | TokenPrices memory tokenPrices 816 | * | ) internal returns (MarketUtils.MarketPrices memory prices) { 817 | * | Market.Props memory marketProps = MarketStoreUtils.get( 818 | * | dataStore, 819 | * | marketToUpdate 820 | | ); 821 | | 822 | * | Price.Props memory indexTokenPrice; 823 | * | Price.Props memory longTokenPrice; 824 | * | Price.Props memory shortTokenPrice; 825 | | 826 | * | for (uint256 i = 0; i < tokenPrices.tokens.length; i++) { 827 | * | if (tokenPrices.tokens[i] == marketProps.indexToken) { 828 | * | indexTokenPrice = Price.Props({ 829 | * | min: tokenPrices.minPrices[i] * 830 | * | (10 ** _getPrecision(marketProps.indexToken)), 831 | * | max: tokenPrices.maxPrices[i] * 832 | * | (10 ** _getPrecision(marketProps.indexToken)) 833 | | }); 834 | | } 835 | | 836 | * | if (tokenPrices.tokens[i] == marketProps.longToken) { 837 | * | longTokenPrice = Price.Props({ 838 | * | min: tokenPrices.minPrices[i] * 839 | * | (10 ** _getPrecision(marketProps.longToken)), 840 | * | max: tokenPrices.maxPrices[i] * 841 | * | (10 ** _getPrecision(marketProps.longToken)) 842 | | }); 843 | | } 844 | | 845 | * | if (tokenPrices.tokens[i] == marketProps.shortToken) { 846 | * | shortTokenPrice = Price.Props({ 847 | * | min: tokenPrices.minPrices[i] * 848 | * | (10 ** _getPrecision(marketProps.shortToken)), 849 | * | max: tokenPrices.maxPrices[i] * 850 | * | (10 ** _getPrecision(marketProps.shortToken)) 851 | | }); 852 | | } 853 | | } 854 | | 855 | * | return 856 | * | MarketUtils.MarketPrices({ 857 | * | indexTokenPrice: indexTokenPrice, 858 | * | longTokenPrice: longTokenPrice, 859 | * | shortTokenPrice: shortTokenPrice 860 | | }); 861 | | } 862 | | 863 | * | function _getPrecision(address token) internal view returns (uint256) { 864 | * | if (token == address(WETH)) { 865 | * | return 8; 866 | * | } else if (token == address(WBTC)) { 867 | * | return 20; 868 | * | } else if (token == address(USDC) || token == address(USDT)) { 869 | * | return 18; 870 | * | } else if (token == address(SOL)) { 871 | * | return 17; 872 | | } 873 | | revert("Unsupported token"); 874 | | } 875 | | 876 | | function _getMarketDataBeforeAfter( 877 | | ShiftUtils.CreateShiftParams memory createShiftParams, 878 | | TokenPrices memory tokenPrices, 879 | | bool isAfterShift, 880 | | uint marketTokenAmountToShift 881 | | ) internal returns (ShiftMarketData memory data) { 882 | | Market.Props memory marketFrom = MarketStoreUtils.get( 883 | | dataStore, 884 | | createShiftParams.fromMarket 885 | | ); 886 | | Market.Props memory marketToUpdate = MarketStoreUtils.get( 887 | | dataStore, 888 | | createShiftParams.toMarket 889 | | ); 890 | | 891 | | (data.marketTokenPriceFrom, ) = MarketUtils.getMarketTokenPrice( 892 | | dataStore, 893 | | marketFrom, 894 | | _getMarketPrices(marketFrom.marketToken, tokenPrices) 895 | | .indexTokenPrice, 896 | | _getMarketPrices(marketFrom.marketToken, tokenPrices) 897 | | .longTokenPrice, 898 | | _getMarketPrices(marketFrom.marketToken, tokenPrices) 899 | | .shortTokenPrice, 900 | | keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS")), 901 | | false 902 | | ); 903 | | 904 | | (data.marketTokenPriceTo, ) = MarketUtils.getMarketTokenPrice( 905 | | dataStore, 906 | | marketToUpdate, 907 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices) 908 | | .indexTokenPrice, 909 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices) 910 | | .longTokenPrice, 911 | | _getMarketPrices(marketToUpdate.marketToken, tokenPrices) 912 | | .shortTokenPrice, 913 | | keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS")), 914 | | false 915 | | ); 916 | | 917 | | Market.Props memory marketForWithdrawal = isAfterShift 918 | | ? marketToUpdate 919 | | : marketFrom; 920 | | 921 | | if (!isAfterShift) { 922 | | ( 923 | | data.simulateLongTokenAmountWithdrawal, 924 | | data.simulateShortTokenAmountWithdrawal 925 | | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut( 926 | | dataStore, 927 | | marketForWithdrawal, 928 | | _getMarketPrices(marketForWithdrawal.marketToken, tokenPrices), 929 | | marketTokenAmountToShift, 930 | | address(0), 931 | | ISwapPricingUtils.SwapPricingType.Shift 932 | | ); 933 | | } else { 934 | | ( 935 | | data.simulateLongTokenAmountWithdrawal, 936 | | data.simulateShortTokenAmountWithdrawal 937 | | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut( 938 | | dataStore, 939 | | marketForWithdrawal, 940 | | _getMarketPrices(marketForWithdrawal.marketToken, tokenPrices), 941 | | ERC20(marketForWithdrawal.marketToken).balanceOf( 942 | | address(createShiftParams.receiver) 943 | | ), 944 | | address(0), 945 | | ISwapPricingUtils.SwapPricingType.Shift 946 | | ); 947 | | } 948 | | } 949 | | 950 | * | function _getSwapPath(uint8 seed) internal returns (address[] memory) { 951 | * | address[] memory markets = new address[](4); 952 | * | markets[0] = address(market_0_WETH_USDC); 953 | * | markets[1] = address(market_WBTC_WBTC_USDC); 954 | * | markets[2] = address(market_WETH_WETH_USDC); 955 | * | markets[3] = address(market_WETH_WETH_USDT); 956 | | 957 | * | if (seed == 0) { 958 | | //get some valid path 959 | * | address[] memory path = new address[](2); 960 | * | path[0] = address(market_WETH_WETH_USDC); 961 | * | path[1] = address(market_0_WETH_USDC); 962 | * | return path; 963 | * | } else if (seed == 7) { 964 | * | return new address[](0); //return empty array on specific seed 965 | | } else { 966 | * | uint numMarkets = seed % (markets.length + 1); 967 | * | address[] memory path = new address[](numMarkets); 968 | * | for (uint i = 0; i < numMarkets; i++) { 969 | * | uint index = (seed + i) % (markets.length - i); 970 | * | path[i] = markets[index]; 971 | | 972 | * | markets[index] = markets[markets.length - 1 - i]; 973 | | } 974 | * | return path; 975 | | } 976 | | } 977 | | 978 | * | function _getTokenOut( 979 | | address[] memory swapPath, 980 | | address inputToken 981 | * | ) internal returns (address[] memory, address) { 982 | * | if (swapPath.length == 0) { 983 | * | return (new address[](0), inputToken); 984 | | } 985 | | 986 | * | address currentToken = inputToken; 987 | * | bool isValidPath = true; 988 | | 989 | * | for (uint i = 0; i < swapPath.length; i++) { 990 | * | Market.Props memory market = MarketStoreUtils.get( 991 | * | dataStore, 992 | * | swapPath[i] 993 | | ); 994 | | 995 | * | if (currentToken == market.longToken) { 996 | * | currentToken = market.shortToken; 997 | * | } else if (currentToken == market.shortToken) { 998 | * | currentToken = market.longToken; 999 | | } else { 1000 | | // Invalid market for the current token 1001 | * | isValidPath = false; 1002 | * | break; 1003 | | } 1004 | | } 1005 | | 1006 | * | if (!isValidPath) { 1007 | * | return (new address[](0), address(0)); 1008 | | } 1009 | | 1010 | * | return (swapPath, currentToken); 1011 | | } 1012 | | 1013 | * | function _getAmountsOut( 1014 | | address[] memory marketPath, 1015 | | address inputToken, 1016 | | uint256 amountIn, 1017 | | address uiFeeReceiver, 1018 | | TokenPrices memory tokenPrices 1019 | * | ) internal returns (SwapResult memory) { 1020 | * | GetAmountsOutCache memory cache; 1021 | * | SwapResult memory result; 1022 | | 1023 | * | if (marketPath.length == 0) { 1024 | * | result.amountOut = amountIn; 1025 | * | return result; 1026 | | } 1027 | | 1028 | * | cache.currentToken = inputToken; 1029 | * | cache.currentAmount = amountIn; 1030 | | 1031 | * | for (uint256 i = 0; i < marketPath.length; i++) { 1032 | * | cache.market = MarketStoreUtils.get(dataStore, marketPath[i]); 1033 | * | cache.prices = _getMarketPrices(marketPath[i], tokenPrices); 1034 | | 1035 | * | ( 1036 | * | uint256 stepAmountOut, 1037 | * | int256 stepImpactAmount, 1038 | * | SwapPricingUtils.SwapFees memory stepFees 1039 | *r | ) = reader.getSwapAmountOut( 1040 | * | dataStore, // DataStore dataStore, 1041 | * | cache.market, // Market.Props memory market, 1042 | * | cache.prices, // MarketUtils.MarketPrices memory prices, 1043 | * | cache.currentToken, // address tokenIn, 1044 | * | cache.currentAmount, // uint256 amountIn, 1045 | * | cache.uiFeeReceiver // address uiFeeReceiver 1046 | | ); 1047 | | 1048 | * | cache.currentToken = (cache.currentToken == cache.market.longToken) 1049 | * | ? cache.market.shortToken 1050 | * | : cache.market.longToken; 1051 | * | cache.currentAmount = stepAmountOut; 1052 | | 1053 | * | result.totalImpactAmount += stepImpactAmount; 1054 | * | result.totalFees.feeAmountForPool += stepFees.feeAmountForPool; 1055 | * | result.totalFees.feeReceiverAmount += stepFees.feeReceiverAmount; 1056 | * | result.totalFees.uiFeeAmount += stepFees.uiFeeAmount; 1057 | * | result.amountOut = cache.currentAmount; 1058 | | } 1059 | | 1060 | | // result.amountAfterFees = stepFees.amountAfterFees; 1061 | * | return result; 1062 | | } 1063 | | 1064 | | function _getRandomTokenPair( 1065 | | uint seed, 1066 | | address addressTo 1067 | | ) internal view returns (address, address) { 1068 | | if ( 1069 | | addressTo == market_0_WETH_USDC || 1070 | | addressTo == market_WETH_WETH_USDC 1071 | | ) { 1072 | | return (address(WETH), address(USDC)); 1073 | | } else if (addressTo == market_WBTC_WBTC_USDC) { 1074 | | return (address(WBTC), address(USDC)); 1075 | | } else if (addressTo == market_WETH_WETH_USDC) { 1076 | | return (address(WETH), address(USDC)); 1077 | | } else if (addressTo == market_WETH_WETH_USDT) { 1078 | | return (address(WETH), address(USDT)); 1079 | | } else { 1080 | | address[4] memory tokens = [ 1081 | | address(WETH), 1082 | | address(WBTC), 1083 | | address(USDC), 1084 | | address(USDT) 1085 | | ]; 1086 | | uint randomLongToken = seed % tokens.length; 1087 | | uint randomShortToken = seed % tokens.length; 1088 | | return (tokens[randomLongToken], tokens[randomShortToken]); 1089 | | } 1090 | | } 1091 | | 1092 | | //@author Rappie from Perimetersec 1093 | * | function clampBetween( 1094 | | uint256 value, 1095 | | uint256 low, 1096 | | uint256 high 1097 | * | ) internal returns (uint256) { 1098 | * | if (value < low || value > high) { 1099 | * | uint256 ans = low + (value % (high - low + 1)); 1100 | | 1101 | * | return ans; 1102 | | } 1103 | * | return value; 1104 | | } 1105 | | 1106 | | //@author Rappie from Perimetersec 1107 | | bytes16 internal constant HEX_DIGITS = "0123456789abcdef"; 1108 | | 1109 | * | function toHexString( 1110 | | bytes memory value 1111 | * | ) internal pure returns (string memory) { 1112 | * | bytes memory buffer = new bytes(2 * value.length + 2); 1113 | * | buffer[0] = "0"; 1114 | * | buffer[1] = "x"; 1115 | * | for (uint256 i = 0; i < value.length; i++) { 1116 | * | uint8 valueByte = uint8(value[i]); 1117 | * | buffer[2 * i + 2] = HEX_DIGITS[valueByte >> 4]; 1118 | * | buffer[2 * i + 3] = HEX_DIGITS[valueByte & 0xf]; 1119 | | } 1120 | * | return string(buffer); 1121 | | } 1122 | * | function abs(int256 x) internal pure returns (uint256) { 1123 | * | return x >= 0 ? uint256(x) : uint256(-x); 1124 | | } 1125 | | } 1126 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/DonationSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./PropertiesSetup.sol"; 6 | | 7 | | contract DonationSetup is PropertiesSetup { 8 | | //turned off 9 | | function Donate( 10 | | uint seed, 11 | | uint8 userSeed, 12 | | address addressFrom, 13 | | uint longAmount, 14 | | uint shortAmount 15 | | ) internal { 16 | | uint userIndex = seed % USERS.length; 17 | | addressFrom = _getRandomUser(userSeed); 18 | | 19 | | address addressTo; 20 | | uint randomAddress = seed % 10; 21 | | if (randomAddress == 0) { 22 | | addressTo = address(depositVault); 23 | | } else if (randomAddress == 1) { 24 | | addressTo = address(orderVault); 25 | | } else if (randomAddress == 2) { 26 | | addressTo = address(shiftVault); 27 | | } else if (randomAddress == 3) { 28 | | addressTo = address(withdrawalVault); 29 | | } else if (randomAddress == 4) { 30 | | addressTo = market_0_WETH_USDC; 31 | | } else if (randomAddress == 6) { 32 | | addressTo = market_WBTC_WBTC_USDC; 33 | | } else if (randomAddress == 8) { 34 | | addressTo = market_WETH_WETH_USDC; 35 | | } else { 36 | | addressTo = market_WETH_WETH_USDT; 37 | | } 38 | | 39 | | (address longToken, address shortToken) = _getRandomTokenPair( 40 | | seed, 41 | | addressTo 42 | | ); 43 | | 44 | | bool isWeth = longToken == address(WETH) || shortToken == address(WETH); 45 | | 46 | | (uint longAmountClamped, uint shortAmountClamped) = _getTokenAmounts( 47 | | longAmount, 48 | | shortAmount, 49 | | longToken, 50 | | shortToken, 51 | | addressFrom 52 | | ); 53 | | 54 | | _mintAndSendTokensTo( 55 | | addressFrom, 56 | | addressTo, 57 | | longAmountClamped, 58 | | shortAmountClamped, 59 | | longToken, 60 | | shortToken, 61 | | 0, 62 | | isWeth 63 | | ); 64 | | } 65 | | } 66 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/GMXSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./depositSetup/DepositSpeedup.sol"; 5 | | import "./withdrawSetup/WithdrawSpeedup.sol"; 6 | | import "./positionSetup/PositionSpeedup.sol"; 7 | | import "./positionSetup/GMXPositionSpeedup.sol"; 8 | | import "./shiftSetup/ShiftSpeedup.sol"; 9 | | import "./LiquidationSetup.sol"; 10 | | import "./DonationSetup.sol"; 11 | | 12 | | contract GMXSetup is 13 | | DepositSpeedup, 14 | | WithdrawSpeedup, 15 | | PositionSpeedup, 16 | | GMXPositionSpeedup, 17 | | ShiftSpeedup, 18 | | LiquidationSetup, 19 | | DonationSetup 20 | | //ADL is imported through positions contract 21 | | { 22 | | function SetUpGMX() internal { 23 | | deployment(address(this)); 24 | | marketsSetup(); 25 | | userSetup(); 26 | | deployCallbackCotracts(); 27 | | deployGammaVault1x_WETHUSDC(); 28 | | deployGammaVault2x_WETHUSDC(); 29 | | deployGammaVault3x_WETHUSDC(); 30 | | deployGammaVault1x_WBTCUSDC(); 31 | | deployGammaVault2x_WBTCUSDC(); 32 | | deployGammaVault3x_WBTCUSDC(); 33 | | setVaultsArray(); 34 | | deployDex(); 35 | | 36 | | for (uint i = 0; i < USERS.length; ++i) { 37 | | if (address(USERS[i]).balance > 0) { 38 | | vm.prank(USERS[i]); 39 | | WETH.deposit{value: address(USERS[i]).balance / 2}(); 40 | | } 41 | | MintableToken(address(USDC)).mint(USERS[i], 1000_000_000e6); 42 | | MintableToken(address(USDT)).mint(USERS[i], 1000_000_000e6); 43 | | MintableToken(address(WBTC)).mint(USERS[i], 1_000_000e8); 44 | | } 45 | | 46 | | if (address(paraswapDeployer).balance > 0) { 47 | | uint paraswapDeployerBalance = address(paraswapDeployer).balance; 48 | | vm.prank(paraswapDeployer); 49 | | WETH.deposit{value: paraswapDeployerBalance / 2}(); 50 | | } 51 | | MintableToken(address(USDC)).mint(paraswapDeployer, 1000_000_000e6); 52 | | MintableToken(address(USDT)).mint(paraswapDeployer, 1000_000_000e6); 53 | | MintableToken(address(WBTC)).mint(paraswapDeployer, 1_000_000e8); 54 | | 55 | | setUpDeposits(6, 500e18, 100_000_000e6); 56 | | setUpDeposits(7, 500e18, 100_000_000e6); 57 | | setUpDeposits(8, 500e18, 100_000_000e6); 58 | | setUpDeposits(9, 500e8, 100_000_000e6); 59 | | 60 | | addLiquidityDex(); 61 | | fillVaultMarketMap(); 62 | | setRouterInVault(); 63 | | } 64 | | 65 | | /** 66 | | * 67 | | * GAMMA GUIDED FUNCTIONS 68 | | * 69 | | */ 70 | | 71 | *r | function fuzz_GammaDepositWithOpenPosition( 72 | | uint8 seed, 73 | | uint8 userSeed, 74 | | uint priceSeed 75 | * | ) public { 76 | * | (address vault, , , ) = _gamma_getVault(seed); 77 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 78 | | 79 | * | IncreaseOrder(seed, priceSeed, true); 80 | * | ExecuteOrder(seed, priceSeed, false); 81 | | 82 | * | GammaDeposit(seed, userSeed, priceSeed); 83 | * | NextActionPerps(seed, priceSeed); 84 | * | ExecuteOrder(seed, priceSeed, false); 85 | | 86 | * | NextActionPerps(seed, priceSeed); 87 | | 88 | * | address user = _getRandomUser(userSeed); 89 | | 90 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 91 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 92 | * | } else if (isNextFinalize(vault)) { 93 | | NextActionPerps(seed, priceSeed); 94 | | } 95 | * | if ( 96 | * | initialFlow == PerpetualVault.FLOW.NONE && 97 | * | !PerpetualVaultLens(vault).cancellationTriggered() 98 | | ) { 99 | * | gammaGeneralPostconditions(vault, priceSeed); 100 | | } 101 | * | _invariant_GAMMA_12(vault, user); 102 | | } 103 | | 104 | *r | function fuzz_GammaWithdrawWithOpenPosition( 105 | | uint8 seed, 106 | | uint8 userSeed, 107 | | uint priceSeed 108 | * | ) public { 109 | * | (address vault, , , ) = _gamma_getVault(seed); 110 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 111 | * | IncreaseOrder(seed, priceSeed, true); 112 | * | ExecuteOrder(seed, priceSeed, false); 113 | | 114 | * | GammaWithdraw(seed, userSeed, priceSeed); 115 | * | ExecuteOrder(seed, priceSeed, false); 116 | | 117 | * | NextActionPerps(seed, priceSeed); 118 | * | ExecuteOrder(seed, priceSeed, false); 119 | * | NextActionPerps(seed, priceSeed); 120 | | 121 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 122 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 123 | * | } else if (isNextFinalize(vault)) { 124 | | NextActionPerps(seed, priceSeed); 125 | | } 126 | * | if ( 127 | * | initialFlow == PerpetualVault.FLOW.NONE && 128 | * | !PerpetualVaultLens(vault).cancellationTriggered() 129 | | ) { 130 | * | gammaGeneralPostconditions(vault, priceSeed); 131 | | } 132 | | } 133 | | 134 | *r | function fuzz_GammaOpenPosition1x( 135 | | bool isLong, 136 | | bool isParaswap, 137 | | uint8 seed, 138 | | uint8 userSeed, 139 | | uint priceSeed, 140 | | uint amount 141 | * | ) public { 142 | * | (address vault, , , ) = _gamma_getVault(seed); 143 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 144 | | 145 | * | SwapOrder( 146 | * | isLong, 147 | * | isParaswap, //only paraswap 148 | * | seed, 149 | * | priceSeed, 150 | * | amount 151 | | ); 152 | * | ExecuteOrder(seed, priceSeed, false); 153 | | 154 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 155 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 156 | * | } else if (isNextFinalize(vault)) { 157 | * | NextActionPerps(seed, priceSeed); 158 | | } 159 | * | if ( 160 | * | initialFlow == PerpetualVault.FLOW.NONE && 161 | * | !PerpetualVaultLens(vault).cancellationTriggered() 162 | | ) { 163 | * | gammaGeneralPostconditions(vault, priceSeed); 164 | | } 165 | | } 166 | | 167 | *r | function fuzz_GammaSwitchPositionType( 168 | | uint8 seed, 169 | | uint8 userSeed, 170 | | uint priceSeed 171 | * | ) public { 172 | * | (address vault, , , ) = _gamma_getVault(seed); 173 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 174 | | 175 | * | IncreaseOrder(seed, priceSeed, true); // Open long 176 | * | ExecuteOrder(seed, priceSeed, false); 177 | | 178 | * | IncreaseOrder(seed, priceSeed, false); // Attempt to open short 179 | * | ExecuteOrder(seed, priceSeed, false); // This should close the long position 180 | | 181 | * | NextActionPerps(seed, priceSeed); 182 | | 183 | * | IncreaseOrder(seed, priceSeed, false); // Attempt to open short 184 | * | ExecuteOrder(seed, priceSeed, false); // This should close the long position 185 | | 186 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 187 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 188 | * | } else if (isNextFinalize(vault)) { 189 | | NextActionPerps(seed, priceSeed); 190 | | } 191 | * | if ( 192 | * | initialFlow == PerpetualVault.FLOW.NONE && 193 | * | !PerpetualVaultLens(vault).cancellationTriggered() 194 | | ) { 195 | * | gammaGeneralPostconditions(vault, priceSeed); 196 | | } 197 | | } 198 | | 199 | *r | function fuzz_GammaCloseNonOneLeveragePosition( 200 | | uint8 seed, 201 | | uint8 userSeed, 202 | | uint priceSeed 203 | * | ) public { 204 | * | (address vault, , , ) = _gamma_getVault(seed); 205 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 206 | | 207 | * | IncreaseOrder(seed, priceSeed, true); 208 | * | ExecuteOrder(seed, priceSeed, false); 209 | | 210 | * | DecreasePosition(seed, priceSeed, true); 211 | * | ExecuteOrder(seed, priceSeed, false); 212 | | 213 | * | NextActionPerps(seed, priceSeed); 214 | | 215 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 216 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 217 | * | } else if (isNextFinalize(vault)) { 218 | | NextActionPerps(seed, priceSeed); 219 | | } 220 | * | if ( 221 | * | initialFlow == PerpetualVault.FLOW.NONE && 222 | * | !PerpetualVaultLens(vault).cancellationTriggered() 223 | | ) { 224 | * | gammaGeneralPostconditions(vault, priceSeed); 225 | | } 226 | | } 227 | | 228 | *r | function fuzz_GammaCloseOneLeveragePosition( 229 | | uint8 seed, 230 | | uint8 userSeed, 231 | | uint priceSeed, 232 | | uint swapAmount 233 | * | ) public { 234 | * | (address vault, , , ) = _gamma_getVault(seed); 235 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 236 | | 237 | * | SwapOrder(true, true, seed, priceSeed, swapAmount); 238 | * | ExecuteOrder(seed, priceSeed, false); 239 | | 240 | * | DecreasePosition(seed, priceSeed, true); 241 | * | ExecuteOrder(seed, priceSeed, false); 242 | * | NextActionPerps(seed, priceSeed); 243 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 244 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 245 | * | } else if (isNextFinalize(vault)) { 246 | | NextActionPerps(seed, priceSeed); 247 | | } 248 | * | if ( 249 | * | initialFlow == PerpetualVault.FLOW.NONE && 250 | | !PerpetualVaultLens(vault).cancellationTriggered() 251 | | ) { 252 | | gammaGeneralPostconditions(vault, priceSeed); 253 | | } 254 | | } 255 | | 256 | * | function fuzz_GammaRunNextActionWithdraw( 257 | | uint8 seed, 258 | | uint8 userSeed, 259 | | uint priceSeed 260 | * | ) public { 261 | * | (address vault, , , ) = _gamma_getVault(seed); 262 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 263 | | 264 | * | IncreaseOrder(seed, priceSeed, true); 265 | * | ExecuteOrder(seed, priceSeed, false); 266 | | 267 | * | GammaWithdraw(seed, userSeed, priceSeed); 268 | * | ExecuteOrder(seed, priceSeed, false); 269 | | 270 | * | NextActionPerps(seed, priceSeed); 271 | * | ExecuteOrder(seed, priceSeed, false); 272 | * | NextActionPerps(seed, priceSeed); 273 | | 274 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 275 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 276 | | } else if (isNextFinalize(vault)) { 277 | | NextActionPerps(seed, priceSeed); 278 | | } 279 | * | if ( 280 | * | initialFlow == PerpetualVault.FLOW.NONE && 281 | * | !PerpetualVaultLens(vault).cancellationTriggered() 282 | | ) { 283 | | gammaGeneralPostconditions(vault, priceSeed); 284 | | } 285 | | } 286 | | 287 | *r | function fuzz_GammaDepositTwiceRunNextActionWithdraw( 288 | | uint8 seed, 289 | | uint8 userSeed, 290 | | uint priceSeed 291 | * | ) public { 292 | * | (address vault, , , ) = _gamma_getVault(seed); 293 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 294 | | 295 | * | address user = _getRandomUser(userSeed); 296 | | 297 | * | GammaDeposit(seed, userSeed, priceSeed); 298 | | 299 | * | _invariant_GAMMA_12(vault, user); 300 | | 301 | * | IncreaseOrder(seed, priceSeed, true); 302 | * | ExecuteOrder(seed, priceSeed, false); 303 | | 304 | * | GammaWithdraw(seed, userSeed, priceSeed); 305 | * | ExecuteOrder(seed, priceSeed, false); 306 | | 307 | * | NextActionPerps(seed, priceSeed); 308 | * | ExecuteOrder(seed, priceSeed, false); 309 | * | NextActionPerps(seed, priceSeed); 310 | | 311 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 312 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 313 | * | } else if (isNextFinalize(vault)) { 314 | | NextActionPerps(seed, priceSeed); 315 | * | } else if (isNextFinalize(vault)) {} 316 | * | if ( 317 | * | initialFlow == PerpetualVault.FLOW.NONE && 318 | * | !PerpetualVaultLens(vault).cancellationTriggered() 319 | | ) { 320 | * | gammaGeneralPostconditions(vault, priceSeed); 321 | | } 322 | | } 323 | | 324 | *r | function fuzz_GammaRunNextActionSettle( 325 | | uint8 seed, 326 | | uint8 userSeed, 327 | | uint priceSeed 328 | | ) public { 329 | * | (address vault, , , ) = _gamma_getVault(seed); 330 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 331 | | 332 | * | IncreaseOrder(seed, priceSeed, true); 333 | * | ExecuteOrder(seed, priceSeed, false); 334 | | 335 | * | GammaWithdraw(seed, userSeed, priceSeed); 336 | * | ExecuteOrder(seed, priceSeed, false); 337 | | 338 | * | NextActionPerps(seed, priceSeed); 339 | * | ExecuteOrder(seed, priceSeed, false); 340 | | 341 | * | NextActionPerps(seed, priceSeed); 342 | * | ExecuteOrder(seed, priceSeed, false); 343 | | NextActionPerps(seed, priceSeed); 344 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 345 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 346 | | } else if (isNextFinalize(vault)) { 347 | | NextActionPerps(seed, priceSeed); 348 | | } 349 | | if ( 350 | | initialFlow == PerpetualVault.FLOW.NONE && 351 | | !PerpetualVaultLens(vault).cancellationTriggered() 352 | | ) { 353 | | gammaGeneralPostconditions(vault, priceSeed); 354 | | } 355 | | } 356 | | 357 | *r | function fuzz_AfterOrderExecution_DepositMarketIncrease( 358 | | uint8 seed, 359 | | uint8 userSeed, 360 | | uint priceSeed 361 | * | ) public { 362 | * | (address vault, , , ) = _gamma_getVault(seed); 363 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 364 | | 365 | * | ExecuteOrder(seed, priceSeed, false); 366 | * | NextActionPerps(seed, priceSeed); 367 | * | ExecuteOrder(seed, priceSeed, false); 368 | * | NextActionPerps(seed, priceSeed); //this will execute finalize 369 | | 370 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 371 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 372 | * | } else if (isNextFinalize(vault)) { 373 | | NextActionPerps(seed, priceSeed); 374 | | } 375 | * | if ( 376 | * | initialFlow == PerpetualVault.FLOW.NONE && 377 | | !PerpetualVaultLens(vault).cancellationTriggered() 378 | | ) { 379 | | gammaGeneralPostconditions(vault, priceSeed); 380 | | } 381 | | } 382 | | 383 | *r | function fuzz_AfterOrderExecution_WithdrawMarketDecrease( 384 | | uint8 seed, 385 | | uint8 userSeed, 386 | | uint priceSeed 387 | * | ) public { 388 | * | (address vault, , , ) = _gamma_getVault(seed); 389 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 390 | | 391 | * | IncreaseOrder(seed, priceSeed, true); 392 | * | ExecuteOrder(seed, priceSeed, false); 393 | | 394 | * | GammaWithdraw(seed, userSeed, priceSeed); 395 | * | ExecuteOrder(seed, priceSeed, false); 396 | * | NextActionPerps(seed, priceSeed); 397 | * | ExecuteOrder(seed, priceSeed, false); 398 | * | NextActionPerps(seed, priceSeed); //this will execute finalize 399 | | 400 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 401 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 402 | * | } else if (isNextFinalize(vault)) { 403 | | NextActionPerps(seed, priceSeed); 404 | | } 405 | * | if ( 406 | * | initialFlow == PerpetualVault.FLOW.NONE && 407 | * | !PerpetualVaultLens(vault).cancellationTriggered() 408 | | ) { 409 | * | gammaGeneralPostconditions(vault, priceSeed); 410 | | } 411 | | } 412 | | 413 | *r | function fuzz_AfterOrderExecution_WithdrawMarketSwap( 414 | | uint8 seed, 415 | | uint8 userSeed, 416 | | uint priceSeed, 417 | | uint swapAmount 418 | | ) public { 419 | * | (address vault, , , ) = _gamma_getVault(seed); 420 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 421 | | 422 | * | SwapOrder(true, true, seed, priceSeed, swapAmount); 423 | * | ExecuteOrder(seed, priceSeed, false); 424 | | 425 | * | GammaWithdraw(seed, userSeed, priceSeed); 426 | | 427 | | NextActionPerps(seed, priceSeed); 428 | | ExecuteOrder(seed, priceSeed, false); 429 | | NextActionPerps(seed, priceSeed); //this will execute finalize 430 | | 431 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 432 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 433 | | } else if (isNextFinalize(vault)) { 434 | | NextActionPerps(seed, priceSeed); 435 | | } 436 | | if ( 437 | | initialFlow == PerpetualVault.FLOW.NONE && 438 | | !PerpetualVaultLens(vault).cancellationTriggered() 439 | | ) { 440 | | gammaGeneralPostconditions(vault, priceSeed); 441 | | } 442 | | } 443 | | 444 | *r | function fuzz_AfterOrderExecution_GmxSwapNonCollateralToIndex( 445 | | uint8 seed, 446 | | uint8 userSeed, 447 | | uint priceSeed, 448 | | uint swapAmount 449 | | ) public { 450 | * | (address vault, , , ) = _gamma_getVault(seed); 451 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 452 | | 453 | * | SwapOrder(true, true, seed, priceSeed, swapAmount); 454 | * | ExecuteOrder(seed, priceSeed, false); 455 | | 456 | * | DecreasePosition(seed, priceSeed, true); 457 | * | ExecuteOrder(seed, priceSeed, false); 458 | * | NextActionPerps(seed, priceSeed); 459 | * | ExecuteOrder(seed, priceSeed, false); 460 | | 461 | * | ExecuteOrder(seed, priceSeed, false); 462 | | NextActionPerps(seed, priceSeed); 463 | | NextActionPerps(seed, priceSeed); //this will execute finalize 464 | | 465 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 466 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 467 | | } else if (isNextFinalize(vault)) { 468 | | NextActionPerps(seed, priceSeed); 469 | | } 470 | | if ( 471 | | initialFlow == PerpetualVault.FLOW.NONE && 472 | | !PerpetualVaultLens(vault).cancellationTriggered() 473 | | ) { 474 | | gammaGeneralPostconditions(vault, priceSeed); 475 | | } 476 | | } 477 | | 478 | *r | function fuzz_AfterOrderExecution_CompoundSwapToCollateral( 479 | | uint8 seed, 480 | | uint8 userSeed, 481 | | uint priceSeed, 482 | | uint swapAmount 483 | | ) public { 484 | * | (address vault, , , ) = _gamma_getVault(seed); 485 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 486 | | 487 | * | SwapOrder(true, true, seed, priceSeed, swapAmount); 488 | * | ExecuteOrder(seed, priceSeed, false); 489 | | 490 | * | vm.warp(block.timestamp + 7 days); //collect fees 491 | | 492 | * | NextActionPerps(seed, priceSeed); 493 | * | ExecuteOrder(seed, priceSeed, false); 494 | * | NextActionPerps(seed, priceSeed); 495 | * | ExecuteOrder(seed, priceSeed, false); 496 | * | NextActionPerps(seed, priceSeed); 497 | * | NextActionPerps(seed, priceSeed); 498 | | 499 | | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 500 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 501 | | } else if (isNextFinalize(vault)) { 502 | | NextActionPerps(seed, priceSeed); 503 | | } 504 | | if ( 505 | | initialFlow == PerpetualVault.FLOW.NONE && 506 | | !PerpetualVaultLens(vault).cancellationTriggered() 507 | | ) { 508 | | gammaGeneralPostconditions(vault, priceSeed); 509 | | } 510 | | } 511 | | 512 | *r | function fuzz_Coverage01_SwitchPositionType( 513 | | uint8 seed, 514 | | uint8 userSeed, 515 | | uint priceSeed 516 | * | ) public { 517 | * | (address vault, , , ) = _gamma_getVault(seed); 518 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 519 | | 520 | * | IncreaseOrder(seed, priceSeed, true); // Open long 521 | * | ExecuteOrder(seed, priceSeed, false); 522 | | 523 | * | bool isLong = false; //short 524 | * | IncreaseOrder(seed, priceSeed, isLong); 525 | * | ExecuteOrder(seed, priceSeed, false); 526 | | 527 | * | NextActionPerps(seed, priceSeed); 528 | * | ExecuteOrder(seed, priceSeed, false); 529 | * | NextActionPerps(seed, priceSeed); 530 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 531 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 532 | * | } else if (isNextFinalize(vault)) { 533 | | NextActionPerps(seed, priceSeed); 534 | | } 535 | * | if ( 536 | * | initialFlow == PerpetualVault.FLOW.NONE && 537 | * | !PerpetualVaultLens(vault).cancellationTriggered() 538 | | ) { 539 | * | gammaGeneralPostconditions(vault, priceSeed); 540 | | } 541 | | } 542 | | 543 | *r | function fuzz_withdrawAndCheckFees( 544 | | uint8 vaultSeed, 545 | | uint8 userSeed, 546 | | uint priceSeed, 547 | | bool isLong 548 | * | ) public { 549 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 550 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 551 | *r | require( 552 | * | PerpetualVault(vault).curPositionKey() != bytes32(0), 553 | | "Position should be opened" 554 | | ); 555 | | 556 | * | _positionBefore(); 557 | * | if (states[0].vaultInfos[vault].totalFees > 0) { 558 | * | DecreasePosition(vaultSeed, priceSeed, isLong); 559 | | 560 | * | ExecuteOrder(vaultSeed, priceSeed, true); //isAtomic 561 | * | NextActionPerps(vaultSeed, priceSeed); 562 | | 563 | * | _gammaBefore(); 564 | | ( 565 | | , 566 | * | uint initialDepositAmount, 567 | * | uint depositTimestamp 568 | * | ) = GammaWithdraw(vaultSeed, userSeed, priceSeed); 569 | | _positionAfter(); 570 | | require( 571 | | states[1].vaultInfos[vault].totalFees == 0, 572 | | "Position wasn't closed" 573 | | ); 574 | | if ( 575 | | initialFlow == PerpetualVault.FLOW.NONE && 576 | | !PerpetualVaultLens(vault).cancellationTriggered() 577 | | ) { 578 | | gammaGeneralPostconditions(vault, priceSeed); 579 | | } 580 | | _invariant_GAMMA_01(userSeed, vaultSeed, initialDepositAmount); 581 | | _invariant_GAMMA_07(vault, depositTimestamp); 582 | | } 583 | | } 584 | | 585 | *r | function fuzz_GammaNextActionCompound( 586 | | uint8 vaultSeed, 587 | | uint8 userSeed, 588 | | uint priceSeed 589 | * | ) public { 590 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 591 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 592 | * | IncreaseExecuteOrder_GuidedBrick_01(userSeed, priceSeed); 593 | * | GammaDeposit(vaultSeed, userSeed, priceSeed); 594 | * | RunNextAction_GuidedBrick_02(vaultSeed, priceSeed); 595 | * | vm.warp(block.timestamp + priceSeed); //collect funding 596 | * | RunNextAction_GuidedBrick_02(vaultSeed, priceSeed); 597 | | } 598 | | 599 | *r | function fuzz_DonateAndCheckExecution( 600 | | uint8 vaultSeed, 601 | | uint8 userSeed, 602 | | uint priceSeed 603 | * | ) public { 604 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 605 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 606 | * | address index = PerpetualVault(vault).indexToken(); 607 | | 608 | * | (PerpetualVault.NextActionSelector currentAction, ) = PerpetualVault( 609 | * | vault 610 | | ).nextAction(); 611 | | 612 | * | IncreaseOrder(userSeed, priceSeed, true); 613 | | 614 | * | (currentAction, ) = PerpetualVault(vault).nextAction(); 615 | * | address nakamoto = _getRandomUser(userSeed + 1); //other user - nakamoto the wealthy 616 | | 617 | * | _mintAndSendTokensTo( 618 | * | nakamoto, 619 | * | address(orderVault), 620 | * | fl.clamp(priceSeed, 0, WETH.balanceOf(nakamoto)), //long token 621 | * | fl.clamp(priceSeed, 0, USDC.balanceOf(nakamoto)), //short token 622 | * | address(index), 623 | * | address(USDC), 624 | * | 0, 625 | * | false 626 | | ); 627 | * | ExecuteOrder(userSeed, priceSeed, false); 628 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 629 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 630 | * | } else if (isNextFinalize(vault)) { 631 | * | NextActionPerps(vaultSeed, priceSeed); 632 | | } 633 | | 634 | * | if ( 635 | * | initialFlow == PerpetualVault.FLOW.NONE && 636 | * | !PerpetualVaultLens(vault).cancellationTriggered() 637 | | ) { 638 | * | gammaGeneralPostconditions(vault, priceSeed); 639 | | } 640 | | } 641 | | 642 | *r | function fuzz_openAndLiquidatePosition( 643 | | uint8 vaultSeed, 644 | | uint8 userSeed, 645 | | uint priceSeed 646 | * | ) public { 647 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 648 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 649 | | 650 | * | GammaDeposit(vaultSeed, userSeed, priceSeed); 651 | | 652 | * | IncreaseOrder(vaultSeed, priceSeed, true); // Open long 653 | * | ExecuteOrder(vaultSeed, priceSeed, false); 654 | | 655 | * | LiquidateVault(vaultSeed); 656 | | 657 | * | (bool success, , ) = GammaWithdraw(vaultSeed, userSeed, priceSeed); 658 | * | fl.t(success, "GAMMA-15: WIthdraw failed afted liquidation"); 659 | | 660 | * | ExecuteOrder(vaultSeed, priceSeed, false); 661 | | 662 | * | NextActionPerps(vaultSeed, priceSeed); 663 | * | ExecuteOrder(vaultSeed, priceSeed, false); //retry 664 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 665 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 666 | * | } else if (isNextFinalize(vault)) { 667 | | NextActionPerps(vaultSeed, priceSeed); 668 | | } 669 | * | if ( 670 | * | initialFlow == PerpetualVault.FLOW.NONE && 671 | * | !PerpetualVaultLens(vault).cancellationTriggered() 672 | | ) { 673 | | gammaGeneralPostconditions(vault, priceSeed); 674 | | } 675 | | } 676 | | 677 | * | function fuzz_openAndADLVault_PriceGuided( 678 | | uint8 vaultSeed, 679 | | uint8 userSeed, 680 | | uint priceSeed 681 | * | ) public { 682 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 683 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 684 | | 685 | * | uint priceSeed = 1000e4; //from 1k 686 | | 687 | * | GammaDepositAmount(vaultSeed, userSeed, priceSeed, 83000e6); //to 250k x3 lev 688 | | 689 | * | IncreaseOrder(vaultSeed, priceSeed, true); 690 | * | ExecuteOrder(vaultSeed, priceSeed, false); 691 | | 692 | * | ExecuteADLonVault(vaultSeed, 999999e4); 693 | | 694 | * | (bool success, , ) = GammaWithdraw(vaultSeed, userSeed, priceSeed); 695 | * | fl.t(success, "GAMMA-16: WIthdraw failed afted ADL"); 696 | | 697 | * | ExecuteOrder(vaultSeed, priceSeed, false); 698 | | 699 | * | NextActionPerps(vaultSeed, priceSeed); 700 | * | ExecuteOrder(vaultSeed, priceSeed, false); 701 | * | NextActionPerps(vaultSeed, priceSeed); 702 | * | gammaGeneralPostconditions(vault, priceSeed); 703 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 704 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 705 | * | } else if (isNextFinalize(vault)) { 706 | | NextActionPerps(vaultSeed, priceSeed); 707 | | } 708 | * | if ( 709 | * | initialFlow == PerpetualVault.FLOW.NONE && 710 | * | !PerpetualVaultLens(vault).cancellationTriggered() 711 | | ) { 712 | * | gammaGeneralPostconditions(vault, priceSeed); 713 | | } 714 | | } 715 | | 716 | *r | function fuzz_openAndADLVault_Free( 717 | | uint8 vaultSeed, 718 | | uint8 userSeed, 719 | | uint priceSeed 720 | * | ) public { 721 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 722 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 723 | | 724 | * | GammaDepositAmount( 725 | * | vaultSeed, 726 | * | userSeed, 727 | * | priceSeed, 728 | * | priceSeed / vaultSeed 729 | | ); 730 | | 731 | * | IncreaseOrder(vaultSeed, priceSeed, true); 732 | * | ExecuteOrder(vaultSeed, priceSeed, false); 733 | | 734 | * | ExecuteADLonVault(vaultSeed, priceSeed); 735 | | 736 | * | GammaWithdraw(vaultSeed, userSeed, priceSeed); 737 | * | ExecuteOrder(vaultSeed, priceSeed, false); 738 | | 739 | * | NextActionPerps(vaultSeed, priceSeed); 740 | * | ExecuteOrder(vaultSeed, priceSeed, false); 741 | * | NextActionPerps(vaultSeed, priceSeed); 742 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 743 | | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 744 | * | } else if (isNextFinalize(vault)) { 745 | | NextActionPerps(vaultSeed, priceSeed); 746 | | } 747 | * | if ( 748 | * | initialFlow == PerpetualVault.FLOW.NONE && 749 | * | !PerpetualVaultLens(vault).cancellationTriggered() 750 | | ) { 751 | * | gammaGeneralPostconditions(vault, priceSeed); 752 | | } 753 | | } 754 | | 755 | | /* 756 | | * 757 | | * GAMMA REMEDIATIONS COVERAGE GUIDANCE 758 | | * 759 | | */ 760 | | 761 | *r | function fuzz_GammaDepositOpenCloseDonateWETH_Finalize( 762 | | uint8 vaultSeed, 763 | | uint8 userSeed, 764 | | uint priceSeed 765 | * | ) public { 766 | * | (address vault, , , ) = _gamma_getVault(vaultSeed); 767 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 768 | * | address index = PerpetualVault(vault).indexToken(); 769 | | 770 | * | IncreaseOrder(vaultSeed, priceSeed, true); //isLong 771 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 772 | | 773 | * | DecreasePosition( 774 | * | vaultSeed, 775 | * | priceSeed / fl.clamp(userSeed, 1, 10), 776 | * | true 777 | | ); 778 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 779 | | 780 | * | _mintAndSendTokensTo( 781 | * | _getRandomUser(1), 782 | * | address(vault), 783 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary 784 | * | 0, 785 | * | address(index), 786 | * | address(0), 787 | * | 0, 788 | * | false 789 | | ); 790 | | 791 | * | NextActionPerps(vaultSeed, priceSeed); 792 | | 793 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 794 | * | ExecuteOrder(vaultSeed, priceSeed, false); //isAtomic 795 | * | } else if (isNextFinalize(vault)) { 796 | | NextActionPerps(vaultSeed, priceSeed); 797 | | } 798 | * | if ( 799 | * | initialFlow == PerpetualVault.FLOW.NONE && 800 | * | !PerpetualVaultLens(vault).cancellationTriggered() 801 | | ) { 802 | * | gammaGeneralPostconditions(vault, priceSeed); 803 | | } 804 | | } 805 | | 806 | *r | function fuzz_GammaDepositWithOpenPositionDonateWETH( 807 | | uint8 seed, 808 | | uint8 userSeed, 809 | | uint priceSeed 810 | * | ) public { 811 | * | (address vault, , , ) = _gamma_getVault(seed); 812 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 813 | * | address index = PerpetualVault(vault).indexToken(); 814 | | 815 | * | GammaDeposit(seed, userSeed, priceSeed); 816 | | 817 | * | _mintAndSendTokensTo( 818 | * | _getRandomUser(1), 819 | * | address(vault), 820 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary, 821 | * | 0, 822 | * | address(index), 823 | * | address(0), 824 | * | 0, 825 | * | false 826 | | ); 827 | | 828 | * | IncreaseOrder(seed, priceSeed, false); 829 | | 830 | * | ExecuteOrder(seed, priceSeed, false); 831 | | 832 | * | GammaDeposit(seed, userSeed, priceSeed); 833 | | 834 | * | NextActionPerps(seed, priceSeed); 835 | | 836 | * | ExecuteOrder(seed, priceSeed, false); 837 | | 838 | * | NextActionPerps(seed, priceSeed); 839 | | // NextActionPerps(seed, priceSeed); 840 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 841 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 842 | * | } else if (isNextFinalize(vault)) { 843 | | NextActionPerps(seed, priceSeed); 844 | | } 845 | | 846 | * | if ( 847 | * | initialFlow == PerpetualVault.FLOW.NONE && 848 | * | !PerpetualVaultLens(vault).cancellationTriggered() 849 | | ) { 850 | * | gammaGeneralPostconditions(vault, priceSeed); 851 | | } 852 | | } 853 | | 854 | *r | function fuzz_SwitchPositionType_Donate( 855 | | uint8 seed, 856 | | uint8 userSeed, 857 | | uint priceSeed 858 | * | ) public { 859 | * | (address vault, , , ) = _gamma_getVault(seed); 860 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 861 | * | address index = PerpetualVault(vault).indexToken(); 862 | | 863 | * | GammaDeposit(seed, userSeed, priceSeed); 864 | * | _mintAndSendTokensTo( 865 | * | _getRandomUser(1), 866 | * | address(vault), 867 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary, 868 | * | 0, 869 | * | address(index), 870 | * | address(0), 871 | * | 0, 872 | * | false 873 | | ); 874 | * | IncreaseOrder(seed, priceSeed, true); // Open long 875 | | 876 | * | ExecuteOrder(seed, priceSeed, false); 877 | | 878 | * | bool isLong = false; 879 | * | IncreaseOrder(seed, priceSeed, isLong); 880 | | 881 | * | ExecuteOrder(seed, priceSeed, false); 882 | | 883 | * | _mintAndSendTokensTo( 884 | * | _getRandomUser(1), 885 | * | address(vault), 886 | * | fl.clamp(priceSeed, 0, 10e19), //arbitrary, 887 | * | 0, 888 | * | address(index), 889 | * | address(0), 890 | * | 0, 891 | * | false 892 | | ); 893 | | 894 | * | NextActionPerps(seed, priceSeed); 895 | * | ExecuteOrder(seed, priceSeed, false); 896 | | 897 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 898 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 899 | * | } else if (isNextFinalize(vault)) { 900 | | NextActionPerps(seed, priceSeed); 901 | | } 902 | * | if ( 903 | * | initialFlow == PerpetualVault.FLOW.NONE && 904 | * | !PerpetualVaultLens(vault).cancellationTriggered() 905 | | ) { 906 | * | gammaGeneralPostconditions(vault, priceSeed); 907 | | } 908 | | } 909 | | 910 | *r | function fuzz_GammaCloseOneLeveragePosition_Remed( 911 | | uint8 seed, 912 | | uint8 userSeed, 913 | | uint priceSeed 914 | * | ) public { 915 | * | (address vault, , , ) = _gamma_getVault(seed); 916 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 917 | | 918 | * | GammaDeposit(seed, userSeed, priceSeed); 919 | | 920 | * | SwapOrder( 921 | * | true, 922 | * | true, 923 | * | seed, 924 | * | priceSeed, 925 | * | fl.clamp(priceSeed, 100e6, 10000e6) 926 | | ); //arbitrary 927 | | 928 | * | ExecuteOrder(seed, priceSeed, false); 929 | | 930 | * | DecreasePosition(seed, priceSeed, true); 931 | | 932 | * | ExecuteOrder(seed, priceSeed, false); 933 | | 934 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 935 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 936 | * | } else if (isNextFinalize(vault)) { 937 | | NextActionPerps(seed, priceSeed); 938 | | } 939 | * | if ( 940 | * | initialFlow == PerpetualVault.FLOW.NONE && 941 | * | !PerpetualVaultLens(vault).cancellationTriggered() 942 | | ) { 943 | * | gammaGeneralPostconditions(vault, priceSeed); 944 | | } 945 | | } 946 | | 947 | *r | function fuzz_GammaCompoundPositionDonateUSDC( 948 | | uint8 seed, 949 | | uint8 userSeed, 950 | | uint priceSeed 951 | * | ) public { 952 | * | (address vault, , , ) = _gamma_getVault(seed); 953 | * | IncreaseOrder(seed, priceSeed, seed % 2 == 0 ? true : false); //longs/shorts 954 | * | ExecuteOrder(seed, priceSeed, false); 955 | | 956 | * | _mintAndSendTokensTo( 957 | * | _getRandomUser(1), //any 958 | * | address(vault), 959 | * | 0, 960 | * | fl.clamp(priceSeed, 100e6, 10000e9), //arbitrary, 961 | * | address(0), 962 | * | address(USDC), 963 | * | 0, 964 | * | false 965 | | ); 966 | | 967 | * | NextActionPerps(seed, priceSeed); 968 | * | ExecuteOrder(seed, priceSeed, false); 969 | * | NextActionPerps(seed, priceSeed); 970 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 971 | * | ExecuteOrder(seed, priceSeed, false); //isAtomic 972 | * | } else if (isNextFinalize(vault)) { 973 | | NextActionPerps(seed, priceSeed); 974 | | } 975 | | } 976 | | 977 | *r | function fuzz_GammaAfterOrderExecutionDeposit( 978 | | uint8 seed, 979 | | uint8 userSeed, 980 | | uint priceSeed 981 | * | ) public { 982 | * | (address vault, , , ) = _gamma_getVault(seed); 983 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 984 | | 985 | * | IncreaseOrder(seed, priceSeed, true); // Open long 986 | * | ExecuteOrder(seed, priceSeed, false); 987 | * | GammaDepositAmount( 988 | * | seed, 989 | * | userSeed, 990 | * | priceSeed, 991 | * | fl.clamp(priceSeed, 100e6, 10000e9) 992 | | ); //arbitrary 993 | * | NextActionPerps(seed, priceSeed); 994 | * | ExecuteOrder(seed, priceSeed, false); 995 | | 996 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 997 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 998 | * | } else if (isNextFinalize(vault)) { 999 | * | NextActionPerps(seed, priceSeed); 1000 | | } 1001 | * | if ( 1002 | * | initialFlow == PerpetualVault.FLOW.NONE && 1003 | * | !PerpetualVaultLens(vault).cancellationTriggered() 1004 | | ) { 1005 | * | gammaGeneralPostconditions(vault, priceSeed); 1006 | | } 1007 | | } 1008 | | 1009 | *r | function fuzz_GammaAfterOrderExecutionWithdraw( 1010 | | uint8 seed, 1011 | | uint8 userSeed, 1012 | | uint priceSeed 1013 | * | ) public { 1014 | * | (address vault, , , ) = _gamma_getVault(seed); 1015 | * | PerpetualVault.FLOW initialFlow = PerpetualVault(vault).flow(); 1016 | | 1017 | * | GammaDeposit(seed, userSeed, priceSeed); 1018 | * | IncreaseOrder(seed, priceSeed, true); // Open long 1019 | * | ExecuteOrder(seed, priceSeed, false); 1020 | * | GammaWithdraw(seed, userSeed, 50000e4); 1021 | * | NextActionPerps(seed, priceSeed); 1022 | * | ExecuteOrder(seed, priceSeed, false); 1023 | * | if (PerpetualVaultLens(vault)._getGMXLock() == true) { 1024 | | ExecuteOrder(seed, priceSeed, false); //isAtomic 1025 | * | } else if (isNextFinalize(vault)) { 1026 | | NextActionPerps(seed, priceSeed); 1027 | | } 1028 | * | if ( 1029 | * | initialFlow == PerpetualVault.FLOW.NONE && 1030 | * | !PerpetualVaultLens(vault).cancellationTriggered() 1031 | | ) { 1032 | * | gammaGeneralPostconditions(vault, priceSeed); 1033 | | } 1034 | | } 1035 | | 1036 | *r | function IncreaseExecuteOrder_GuidedBrick_01( 1037 | | //long 1038 | | uint8 userSeed, 1039 | | uint priceSeed 1040 | | ) public { 1041 | * | IncreaseOrder(userSeed, priceSeed, true); // Open long 1042 | * | ExecuteOrder(userSeed, priceSeed, false); 1043 | | } 1044 | | 1045 | *r | function RunNextAction_GuidedBrick_02( 1046 | | uint8 vaultSeed, 1047 | | uint priceSeed 1048 | | ) public { 1049 | * | NextActionPerps(vaultSeed, priceSeed); 1050 | * | ExecuteOrder(vaultSeed, priceSeed, false); 1051 | | } 1052 | | } 1053 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/LiquidationSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./PropertiesSetup.sol"; 6 | | import "../../contracts/market/MarketUtils.sol"; 7 | | 8 | | contract LiquidationSetup is PropertiesSetup { 9 | * | function LiquidateVault(uint8 userIndex) public { 10 | * | (, , , address user) = _gamma_getVault(userIndex); //gmxUtils is a holder of position 11 | | 12 | * | uint256 positionCountBefore = PositionStoreUtils.getPositionCount( 13 | * | dataStore 14 | | ); 15 | | 16 | * | Position.Props[] memory positions = reader.getAccountPositions( 17 | * | dataStore, 18 | * | user, 19 | * | 0, 20 | * | 10 21 | | ); //@coverage:limiter 22 | * | Position.Props memory positionToLiquidate = positions[0]; 23 | | 24 | * | bytes32 positionKey = Position.getPositionKey( 25 | * | user, 26 | * | positionToLiquidate.addresses.market, 27 | * | positionToLiquidate.addresses.collateralToken, 28 | * | positionToLiquidate.flags.isLong 29 | | ); 30 | | 31 | * | Market.Props memory marketProps = MarketStoreUtils.get( 32 | * | dataStore, 33 | * | positionToLiquidate.addresses.market 34 | | ); 35 | | 36 | * | TokenPrices memory tokenPrices = _setTokenPrices( 37 | * | 1 //priceseed for the minimal price 38 | | ); 39 | | 40 | * | ( 41 | * | bool isLiquidatable /*string memory */, 42 | | , 43 | * | PositionUtils.IsPositionLiquidatableInfo 44 | | memory isPositionLiquidatableInfo 45 | * | ) = PositionUtils.isPositionLiquidatable( 46 | * | dataStore, 47 | * | referralStorage, 48 | * | positionToLiquidate, //Position.Props memory position, 49 | * | marketProps, //Market.Props memory market, 50 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), //MarketUtils.MarketPrices memory prices 51 | * | true // bool shouldValidateMinCollateralUsd 52 | | ); 53 | | 54 | *r | require(isLiquidatable, "Position is not liquidatable"); 55 | | 56 | * | _liquidate( 57 | * | user, 58 | * | positionToLiquidate.addresses.market, 59 | * | positionToLiquidate.addresses.collateralToken, 60 | * | positionToLiquidate.flags.isLong, 61 | * | tokenPrices 62 | | ); 63 | | 64 | * | uint256 positionCountAfter = PositionStoreUtils.getPositionCount( 65 | * | dataStore 66 | | ); 67 | | 68 | * | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils 69 | * | .getAutoCancelOrderKeys(dataStore, positionKey); 70 | | 71 | * | invariantPositionCountShouldDecrease( 72 | * | positionCountAfter, 73 | * | positionCountBefore 74 | | ); 75 | * | invariantPositionCountDecreasesByOne( 76 | * | positionCountAfter, 77 | * | positionCountBefore 78 | | ); 79 | * | invariantAutoCancelListShouldBeEmptyAfterLiquidation( 80 | * | autoCancelOrderKeys.length 81 | | ); 82 | | 83 | * | _checkPositionLiquitatableCoverage( 84 | * | user, 85 | * | positionToLiquidate.addresses.market, 86 | * | positionToLiquidate.addresses.collateralToken, 87 | * | positionToLiquidate.flags.isLong, 88 | * | isPositionLiquidatableInfo 89 | | ); 90 | | } 91 | | 92 | * | function Liquidate(uint8 userIndex) public { 93 | * | address user = _getRandomUser(userIndex); 94 | | 95 | * | uint256 positionCountBefore = PositionStoreUtils.getPositionCount( 96 | * | dataStore 97 | | ); 98 | | 99 | * | Position.Props[] memory positions = reader.getAccountPositions( 100 | * | dataStore, 101 | * | user, 102 | * | 0, 103 | * | 10 104 | | ); //@coverage:limiter 105 | * | Position.Props memory positionToLiquidate = positions[0]; 106 | | 107 | * | bytes32 positionKey = Position.getPositionKey( 108 | * | user, 109 | * | positionToLiquidate.addresses.market, 110 | * | positionToLiquidate.addresses.collateralToken, 111 | * | positionToLiquidate.flags.isLong 112 | | ); 113 | | 114 | * | Market.Props memory marketProps = MarketStoreUtils.get( 115 | * | dataStore, 116 | * | positionToLiquidate.addresses.market 117 | | ); 118 | | 119 | * | TokenPrices memory tokenPrices = _setTokenPrices( 120 | * | 1 //priceseed for the minimal price 121 | | ); 122 | | 123 | * | ( 124 | * | bool isLiquidatable /*string memory */, 125 | | , 126 | * | PositionUtils.IsPositionLiquidatableInfo 127 | | memory isPositionLiquidatableInfo 128 | * | ) = PositionUtils.isPositionLiquidatable( 129 | * | dataStore, 130 | * | referralStorage, 131 | * | positionToLiquidate, //Position.Props memory position, 132 | * | marketProps, //Market.Props memory market, 133 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), //MarketUtils.MarketPrices memory prices 134 | * | true // bool shouldValidateMinCollateralUsd 135 | | ); 136 | | 137 | *r | require(isLiquidatable, "Position is not liquidatable"); 138 | | 139 | | _liquidate( 140 | | user, 141 | | positionToLiquidate.addresses.market, 142 | | positionToLiquidate.addresses.collateralToken, 143 | | positionToLiquidate.flags.isLong, 144 | | tokenPrices 145 | | ); 146 | | 147 | | uint256 positionCountAfter = PositionStoreUtils.getPositionCount( 148 | | dataStore 149 | | ); 150 | | 151 | | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils 152 | | .getAutoCancelOrderKeys(dataStore, positionKey); 153 | | 154 | | invariantPositionCountShouldDecrease( 155 | | positionCountAfter, 156 | | positionCountBefore 157 | | ); 158 | | invariantPositionCountDecreasesByOne( 159 | | positionCountAfter, 160 | | positionCountBefore 161 | | ); 162 | | invariantAutoCancelListShouldBeEmptyAfterLiquidation( 163 | | autoCancelOrderKeys.length 164 | | ); 165 | | 166 | | _checkPositionLiquitatableCoverage( 167 | | user, 168 | | positionToLiquidate.addresses.market, 169 | | positionToLiquidate.addresses.collateralToken, 170 | | positionToLiquidate.flags.isLong, 171 | | isPositionLiquidatableInfo 172 | | ); 173 | | } 174 | | 175 | * | function _liquidate( 176 | | address account, 177 | | address market, 178 | | address collateralToken, 179 | | bool isLong, 180 | | TokenPrices memory tokenPrices 181 | * | ) internal { 182 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 183 | * | tokenPrices.tokens, 184 | * | tokenPrices.maxPrices, 185 | * | tokenPrices.minPrices 186 | | ); 187 | | 188 | * | vm.prank(DEPLOYER); 189 | * | (bool success, bytes memory data) = address(liquidationHandler).call( 190 | * | abi.encodeWithSelector( 191 | * | LiquidationHandler.executeLiquidation.selector, 192 | * | account, 193 | * | market, 194 | * | collateralToken, 195 | * | isLong, 196 | * | oracleParams 197 | | ) 198 | | ); 199 | * | if (!success) { 200 | | invariantDoesNotSilentRevert(data); 201 | | } 202 | | } 203 | | } 204 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/MintSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./BaseSetup.sol"; 5 | | 6 | | contract MintSetup is BaseSetup { 7 | * | function _mintAndSendTokensTo( 8 | | address user, 9 | | address to, 10 | | uint256 longTokenAmount, 11 | | uint256 shortTokenAmount, 12 | | address longTokenAddress, 13 | | address shortTokenAddress, 14 | | uint executionFee, 15 | | bool isWETH 16 | | ) internal { 17 | * | if (longTokenAddress != address(0)) { 18 | * | _handleTokenMintAndTransfer( 19 | * | user, 20 | * | to, 21 | * | longTokenAmount, 22 | * | longTokenAddress, 23 | * | executionFee, 24 | * | isWETH 25 | | ); 26 | | } 27 | | 28 | * | if (shortTokenAddress != address(0)) { 29 | * | _handleTokenMintAndTransfer( 30 | * | user, 31 | * | to, 32 | * | shortTokenAmount, 33 | * | shortTokenAddress, 34 | * | executionFee, 35 | * | isWETH 36 | | ); 37 | | } 38 | | 39 | * | vm.prank(user); 40 | * | WETH.deposit{value: executionFee}(); 41 | * | vm.prank(user); 42 | * | WETH.transfer(to, executionFee); 43 | | } 44 | | 45 | * | function _handleTokenMintAndTransfer( 46 | | address user, 47 | | address to, 48 | | uint256 amount, 49 | | address tokenAddress, 50 | | uint executionFee, 51 | | bool isWETH 52 | | ) private { 53 | * | if (isWETH && tokenAddress == address(WETH)) { 54 | | //mint happens in FuzzSetup 55 | * | vm.prank(user); 56 | *r | WETH.transfer(to, amount); 57 | | } else { 58 | * | vm.prank(user); 59 | *r | MintableToken(tokenAddress).transfer(to, amount); 60 | | } 61 | | } 62 | | } 63 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/OracleSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./BaseSetup.sol"; 5 | | 6 | | contract OracleSetup is BaseSetup { 7 | | mapping(address => uint256) private minTokenPrices; 8 | | mapping(address => uint256) private maxTokenPrices; 9 | | 10 | * | function SetOraclePrices( 11 | | address[] memory tokens, 12 | | uint256[] memory maxPrices, 13 | | uint256[] memory minPrices 14 | * | ) internal returns (OracleUtils.SetPricesParams memory) { 15 | * | require( 16 | * | tokens.length == minPrices.length && tokens.length == maxPrices.length, 17 | | "Tokens, minPrices, and maxPrices arrays must have the same length" 18 | | ); 19 | | 20 | * | for (uint256 i = 0; i < tokens.length; i++) { 21 | * | _setMinPrice(tokens[i], minPrices[i]); 22 | * | _setMaxPrice(tokens[i], maxPrices[i]); 23 | | } 24 | | 25 | * | OracleUtils.SetPricesParams memory oracleParams = _setupOracleParams(tokens); 26 | * | return oracleParams; 27 | | } 28 | | 29 | | function SetOraclePrices( 30 | | address[] memory tokens, 31 | | uint[] memory prices 32 | | ) internal returns (OracleUtils.SetPricesParams memory) { 33 | | require( 34 | | tokens.length == prices.length, 35 | | "Tokens and prices arrays must have the same length" 36 | | ); 37 | | 38 | | for (uint256 i = 0; i < tokens.length; i++) { 39 | | _setMinPrice(tokens[i], prices[i]); 40 | | _setMaxPrice(tokens[i], prices[i]); 41 | | } 42 | | 43 | | OracleUtils.SetPricesParams memory oracleParams = _setupOracleParams(tokens); 44 | | 45 | | return oracleParams; 46 | | } 47 | | 48 | * | function _setMinPrice(address token, uint256 price) internal { 49 | * | require(price > 0, "Zero price is not supported"); 50 | * | require( 51 | * | token == address(WETH) || 52 | * | token == address(WBTC) || 53 | * | token == address(USDC) || 54 | * | token == address(USDT) || 55 | * | token == SOL, 56 | | "Unsupported token" 57 | | ); 58 | * | minTokenPrices[token] = price; 59 | | } 60 | | 61 | * | function _setMaxPrice(address token, uint256 price) internal { 62 | * | require( 63 | * | token == address(WETH) || 64 | * | token == address(WBTC) || 65 | * | token == address(USDC) || 66 | * | token == address(USDT) || 67 | * | token == address(SOL), 68 | | "Unsupported token" 69 | | ); 70 | * | maxTokenPrices[token] = price; 71 | | } 72 | | 73 | * | function _setupOracleParams( 74 | | address[] memory tokens 75 | * | ) internal returns (OracleUtils.SetPricesParams memory) { 76 | * | uint256[] memory precisions = _getPrecisions(tokens); 77 | * | uint256[] memory minPrices = _getMinPrices(tokens); 78 | * | uint256[] memory maxPrices = _getMaxPrices(tokens); 79 | * | address[] memory providers = _getProviders(tokens); 80 | | 81 | * | _setTokenPrices(tokens, minPrices, maxPrices, precisions, providers); 82 | | 83 | * | OracleUtils.SetPricesParams memory oracleParams = OracleUtils.SetPricesParams({ 84 | * | tokens: tokens, 85 | * | providers: providers, 86 | * | data: new bytes[](tokens.length) 87 | | }); 88 | | 89 | * | return oracleParams; 90 | | } 91 | | 92 | * | function _setTokenPrices( 93 | | address[] memory tokens, 94 | | uint256[] memory minPrices, 95 | | uint256[] memory maxPrices, 96 | | uint256[] memory precisions, 97 | | address[] memory providers 98 | | ) internal { 99 | * | for (uint256 i = 0; i < tokens.length; i++) { 100 | * | chainlinkMock.setOraclePrice(tokens[i], minPrices[i], maxPrices[i], precisions[i]); 101 | | } 102 | | } 103 | | 104 | * | function _getPrecisions(address[] memory tokens) internal view returns (uint256[] memory) { 105 | * | uint256[] memory precisions = new uint[](tokens.length); 106 | * | for (uint256 i = 0; i < tokens.length; i++) { 107 | * | precisions[i] = _getPrecision(tokens[i]); 108 | | } 109 | * | return precisions; 110 | | } 111 | | 112 | * | function _getMinPrices(address[] memory tokens) internal view returns (uint256[] memory) { 113 | * | uint256[] memory minPrices = new uint[](tokens.length); 114 | * | for (uint256 i = 0; i < tokens.length; i++) { 115 | * | minPrices[i] = _getMinPrice(tokens[i]); 116 | | } 117 | * | return minPrices; 118 | | } 119 | | 120 | * | function _getMaxPrices(address[] memory tokens) internal view returns (uint256[] memory) { 121 | * | uint256[] memory maxPrices = new uint[](tokens.length); 122 | * | for (uint256 i = 0; i < tokens.length; i++) { 123 | * | maxPrices[i] = _getMaxPrice(tokens[i]); 124 | | } 125 | * | return maxPrices; 126 | | } 127 | | 128 | * | function _getProviders(address[] memory tokens) internal view returns (address[] memory) { 129 | * | address[] memory providers = new address[](tokens.length); 130 | * | for (uint256 i = 0; i < tokens.length; i++) { 131 | * | providers[i] = address(chainlinkMock); 132 | | } 133 | * | return providers; 134 | | } 135 | | 136 | * | function _getMinPrice(address token) internal view returns (uint256) { 137 | * | uint256 price = minTokenPrices[token]; 138 | | 139 | * | require(price != 0, "Min price not set for token"); 140 | * | return price; 141 | | } 142 | | 143 | * | function _getMaxPrice(address token) internal view returns (uint256) { 144 | * | uint256 price = maxTokenPrices[token]; 145 | | 146 | * | require(price != 0, "Max price not set for token"); 147 | * | return price; 148 | | } 149 | | } 150 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/PropertiesSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./OracleSetup.sol"; 5 | | import "./MintSetup.sol"; 6 | | import "../properties/Properties.sol"; 7 | | 8 | | contract PropertiesSetup is OracleSetup, MintSetup, Properties {} 9 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/depositSetup/DepositSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../../contracts/market/MarketUtils.sol"; 6 | | import "../../../contracts/deposit/DepositUtils.sol"; 7 | | import "./../PropertiesSetup.sol"; 8 | | 9 | | contract DepositSetup is PropertiesSetup { 10 | | DepositCreated[] internal depositCreatedArray; 11 | | 12 | | /** 13 | | // 14 | | // GAMMA deposits 15 | | // 16 | | */ 17 | | 18 | *r | function GammaDeposit(uint8 seed, uint8 userSeed, uint priceSeed) public { 19 | | //--GAMMA REVERT DEPOSIT START 20 | | //WITHOUT SETTING PRICES IN GMX ORACLE WE CAN NOT DEPOSIT 21 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 22 | | 23 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 24 | * | tokenPrices.tokens, 25 | * | tokenPrices.maxPrices, 26 | * | tokenPrices.minPrices 27 | | ); 28 | * | vm.prank(DEPLOYER); 29 | * | oracle.setPrices(oracleParams); 30 | | //--GAMMA REVERT DEPOSIT END 31 | | 32 | * | (address vault, , , ) = _gamma_getVault(seed); 33 | *r | require( 34 | * | PerpetualVaultLens(vault).checkForCleanStart(), 35 | | "Previous call was not executed" 36 | | ); 37 | * | uint256 amount = fl.clamp( 38 | * | priceSeed, 39 | * | PerpetualVault(vault).minDepositAmount(), 40 | * | PerpetualVault(vault).maxDepositAmount() 41 | | ); 42 | * | IERC20 collateralToken = PerpetualVault(vault).collateralToken(); 43 | * | address user = _getRandomUser(userSeed); 44 | * | uint256 executionFee = PerpetualVault(vault).getExecutionGasLimit(true); 45 | | 46 | * | vm.prank(user); 47 | * | collateralToken.approve(vault, type(uint256).max); 48 | | 49 | | //prank inside:) 50 | * | (bool success, bytes memory returnData) = _gamma_DepositCall( 51 | * | user, 52 | * | vault, 53 | * | amount, 54 | * | executionFee 55 | | ); 56 | | 57 | * | if (returnData.length > 0) { 58 | * | fl.log( 59 | | "Gamma deposit return data", 60 | * | abi.decode(returnData, (string)) 61 | | ); 62 | | } 63 | | //--GAMMA REVERT DEPOSIT START 64 | * | vm.prank(DEPLOYER); 65 | * | oracle.clearAllPrices(); 66 | | //--GAMMA REVERT DEPOSIT START 67 | | 68 | * | require(success, "Deposit to Gamma failed"); 69 | | } 70 | | 71 | *r | function GammaCancelDeposit(uint8 seed) public { 72 | * | (address vault, , , ) = _gamma_getVault(seed); 73 | | 74 | * | (bool success, bytes memory returnData) = _gamma_CanceDepositCall( 75 | * | vault, 76 | * | gammaKeeper 77 | | ); 78 | *r | require(success, "Cancel Deposit failed "); 79 | | } 80 | * | function GammaDepositAmount( 81 | | uint8 seed, 82 | | uint8 userSeed, 83 | | uint priceSeed, 84 | | uint specificAmount 85 | * | ) public { 86 | | //--GAMMA REVERT DEPOSIT START 87 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 88 | | 89 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 90 | * | tokenPrices.tokens, 91 | * | tokenPrices.maxPrices, 92 | * | tokenPrices.minPrices 93 | | ); 94 | * | vm.prank(DEPLOYER); 95 | * | oracle.setPrices(oracleParams); 96 | | //--GAMMA REVERT DEPOSIT END 97 | | 98 | * | (address vault, , , ) = _gamma_getVault(seed); 99 | *r | require( 100 | * | PerpetualVaultLens(vault).checkForCleanStart(), 101 | | "Previous call was not executed" 102 | | ); 103 | | 104 | * | IERC20 collateralToken = PerpetualVault(vault).collateralToken(); 105 | * | address user = _getRandomUser(userSeed); 106 | * | uint256 executionFee = PerpetualVault(vault).getExecutionGasLimit(true); 107 | | 108 | * | vm.prank(user); 109 | * | collateralToken.approve(vault, type(uint256).max); 110 | | 111 | | //prank inside:) 112 | * | (bool success, bytes memory returnData) = _gamma_DepositCall( 113 | * | user, 114 | * | vault, 115 | * | specificAmount, 116 | * | executionFee 117 | | ); 118 | | 119 | * | if (returnData.length > 0) { 120 | * | fl.log( 121 | | "Gamma deposit return data", 122 | * | abi.decode(returnData, (string)) 123 | | ); 124 | | } 125 | | //--GAMMA REVERT DEPOSIT START 126 | * | vm.prank(DEPLOYER); 127 | * | oracle.clearAllPrices(); 128 | | //--GAMMA REVERT DEPOSIT START 129 | | 130 | * | require(success, "Deposit to Gamma failed"); 131 | | } 132 | | 133 | | /** 134 | | // 135 | | // GMX deposits 136 | | // 137 | | */ 138 | | 139 | *r | function CreateDeposit( 140 | | uint8 marketIndex, 141 | | uint8 userIndex, 142 | | uint longAmount, 143 | | uint shortAmount, 144 | | uint priceSeed, 145 | | uint executionFee, 146 | | uint8 swapPathSeed 147 | * | ) public returns (DepositCreated memory depositCreated) { 148 | * | depositCreated = _createDeposit( 149 | * | marketIndex, 150 | * | userIndex, 151 | * | longAmount, 152 | * | shortAmount, 153 | * | priceSeed, 154 | * | SWAPS_ENABLED ? swapPathSeed : 7, //7 is empty swap path 155 | * | executionFee, 156 | * | false 157 | | ); 158 | | return depositCreated; 159 | | } 160 | | 161 | * | function _createDeposit( 162 | | uint8 marketIndex, 163 | | uint8 userIndex, 164 | | uint longAmount, 165 | | uint shortAmount, 166 | | uint priceSeed, 167 | | uint8 swapPathSeed, 168 | | uint executionFee, 169 | | bool InitialDeposit 170 | * | ) internal returns (DepositCreated memory depositCreated) { 171 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT; 172 | | 173 | * | if (!SWAPS_ENABLED) { 174 | * | swapPathSeed = 7; 175 | | } 176 | | //avoiding stack too deep 177 | * | depositCreated.longSwapPath = _getSwapPath(swapPathSeed); 178 | * | depositCreated.shortSwapPath = _getSwapPath( 179 | * | SWAPS_ENABLED ? swapPathSeed / 5 : 7 180 | | ); //another path 181 | | 182 | * | address user = _getRandomUser(userIndex); 183 | * | address market = _getMarketAddress(marketIndex); 184 | | 185 | * | Market.Props memory marketProps = MarketStoreUtils.get( 186 | * | dataStore, 187 | * | market 188 | | ); 189 | | 190 | * | (longAmount, shortAmount) = _getTokenAmounts( 191 | * | longAmount, 192 | * | shortAmount, 193 | * | marketProps.longToken, 194 | * | marketProps.shortToken, 195 | * | user 196 | | ); 197 | | 198 | * | bool isWETH = marketProps.longToken == address(WETH) || 199 | * | marketProps.shortToken == address(WETH); 200 | | 201 | * | DepositorParams memory depositorParams = _setDepositorParams( 202 | * | user, 203 | * | longAmount, 204 | * | shortAmount, 205 | * | isWETH 206 | | ); 207 | | 208 | * | DepositParams memory depositParams = _setDepositParams( 209 | * | user, 210 | * | address(callback), 211 | * | address(0), //uiFeeReceiver 212 | * | depositCreated.longSwapPath, 213 | * | depositCreated.shortSwapPath, 214 | * | 1, //minMarketTokens 215 | * | false, //isWETH, not wrapping 216 | * | InitialDeposit ? 0 : FIXED_EXECUTION_FEE_AMOUNT, 217 | * | 200 * 1000 218 | | ); 219 | | 220 | * | depositCreated.depositorParams = depositorParams; 221 | * | depositCreated.depositParams = depositParams; 222 | * | depositCreated.beforeDepositExec.marketTotalSupply = ERC20( 223 | * | marketProps.marketToken 224 | | ).totalSupply(); 225 | * | depositCreated.beforeDepositExec.userBalanceMarket = ERC20( 226 | * | marketProps.marketToken 227 | * | ).balanceOf(depositorParams.user); 228 | | 229 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 230 | * | depositCreated.tokenPrices = tokenPrices; 231 | | 232 | * | ( 233 | * | depositCreated.key, 234 | * | depositCreated.beforeDepositExec.simulateDepositAmountOut, 235 | * | depositCreated.createDepositParams 236 | * | ) = _createDeposit( 237 | * | depositorParams, 238 | * | depositParams, 239 | * | marketProps, 240 | * | tokenPrices, 241 | * | executionFee 242 | | ); 243 | | 244 | * | depositCreatedArray.push(depositCreated); 245 | | 246 | * | _checkCreateDepositCoverage( 247 | * | depositCreated.createDepositParams.market, 248 | * | depositCreated.createDepositParams.initialLongToken, 249 | * | depositCreated.createDepositParams.initialShortToken, 250 | * | depositCreated.tokenPrices, 251 | * | depositCreated.depositorParams.user, 252 | * | depositCreated.depositorParams.longAmount, 253 | * | depositCreated.depositorParams.shortAmount 254 | | ); 255 | | } 256 | | 257 | * | function _createDeposit( 258 | | DepositorParams memory depositorParams, 259 | | DepositParams memory depositParams, 260 | | Market.Props memory marketProps, 261 | | TokenPrices memory tokenPrices, 262 | | uint executionFee 263 | | ) 264 | | internal 265 | | returns ( 266 | * | bytes32 depositKey, 267 | * | uint simulateDepositAmountOut, 268 | * | DepositUtils.CreateDepositParams memory createDepositParams 269 | | ) 270 | * | { 271 | * | createDepositParams = _setDepositParams(depositParams, marketProps); 272 | | 273 | * | _mintAndSendTokensTo( 274 | * | depositorParams.user, 275 | * | address(depositVault), 276 | * | depositorParams.longAmount, 277 | * | depositorParams.shortAmount, 278 | * | marketProps.longToken, 279 | * | marketProps.shortToken, 280 | * | executionFee, 281 | * | depositorParams.isWETH 282 | | ); 283 | | 284 | * | simulateDepositAmountOut = ReaderDepositUtils.getDepositAmountOut( 285 | * | dataStore, 286 | * | marketProps, 287 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 288 | * | depositorParams.longAmount, 289 | * | depositorParams.shortAmount, 290 | * | address(0), 291 | * | ISwapPricingUtils.SwapPricingType.TwoStep, // TwoStep, Shift, Atomic 292 | * | false //includeVirtualInventoryImpact 293 | | ); 294 | | 295 | * | bytes memory callData_CreateDeposit = abi.encodeWithSelector( 296 | * | exchangeRouter.createDeposit.selector, 297 | * | createDepositParams 298 | | ); 299 | * | vm.prank(depositorParams.user); 300 | | 301 | * | ( 302 | * | bool success_CreateDeposit, 303 | * | bytes memory returnData_CreateDeposit 304 | * | ) = address(exchangeRouter).call{gas: 30_000_000}( 305 | * | callData_CreateDeposit 306 | | ); 307 | | 308 | * | if (!success_CreateDeposit) { 309 | | invariantDoesNotSilentRevert(returnData_CreateDeposit); 310 | | } else { 311 | * | depositKey = abi.decode(returnData_CreateDeposit, (bytes32)); 312 | | } 313 | | } 314 | | 315 | *r | function CancelDeposit( 316 | | uint seed, 317 | | bool isAtomicExec 318 | | ) 319 | | public 320 | | returns ( 321 | * | DepositState memory _before, 322 | * | DepositState memory _after, 323 | * | DepositCreated memory depositToCancel 324 | | ) 325 | | { 326 | *r | require( 327 | * | depositCreatedArray.length > 0, 328 | | "No deposits available to cancel" 329 | | ); 330 | | 331 | * | uint256 randomIndex = isAtomicExec 332 | * | ? depositCreatedArray.length - 1 333 | * | : clampBetween(seed, 0, depositCreatedArray.length - 1); 334 | | 335 | * | depositToCancel = depositCreatedArray[randomIndex]; 336 | | 337 | * | _before = _snapDepositState( 338 | * | depositToCancel.createDepositParams.receiver, 339 | * | depositToCancel.createDepositParams.market 340 | | ); 341 | | 342 | * | bytes memory callData_CancelDeposit = abi.encodeWithSelector( 343 | * | exchangeRouter.cancelDeposit.selector, 344 | * | depositToCancel.key 345 | | ); 346 | | 347 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 348 | * | vm.prank(depositToCancel.createDepositParams.receiver); 349 | | 350 | * | ( 351 | * | bool success_CancelDeposit, 352 | * | bytes memory returnData_CancelDeposit 353 | * | ) = address(exchangeRouter).call{gas: 30_000_000}( 354 | * | callData_CancelDeposit 355 | | ); 356 | | 357 | * | if (!success_CancelDeposit) { 358 | * | invariantDoesNotSilentRevert(returnData_CancelDeposit); 359 | | } 360 | | 361 | | _after = _snapDepositState( 362 | | depositToCancel.createDepositParams.receiver, 363 | | depositToCancel.createDepositParams.market 364 | | ); 365 | | 366 | | _checkCancelDepositCoverage( 367 | | depositToCancel.createDepositParams.market, 368 | | depositToCancel.createDepositParams.initialLongToken, 369 | | depositToCancel.createDepositParams.initialShortToken, 370 | | depositToCancel.tokenPrices, 371 | | depositToCancel.depositorParams.user, 372 | | depositToCancel.depositorParams.longAmount, 373 | | depositToCancel.depositorParams.shortAmount 374 | | ); 375 | | } 376 | | 377 | *r | function ExecuteDeposit( 378 | | uint priceSeed, 379 | | bool isAtomicExec 380 | * | ) public returns (DepositCreated memory, DepositState memory) { 381 | *r | require( 382 | * | depositCreatedArray.length > 0, 383 | | "No deposits available to execute" 384 | | ); 385 | | 386 | * | uint256 randomIndex = isAtomicExec 387 | * | ? depositCreatedArray.length - 1 388 | * | : clampBetween(priceSeed, 0, depositCreatedArray.length - 1); 389 | | 390 | * | DepositCreated memory depositToExecute = depositCreatedArray[ 391 | * | randomIndex 392 | | ]; 393 | | 394 | * | Market.Props memory marketProps = MarketStoreUtils.get( 395 | * | dataStore, 396 | * | depositToExecute.createDepositParams.market 397 | | ); 398 | | 399 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 400 | | 401 | | //state before recorded in DepositCreated struct on create deposit step 402 | * | DepositState memory coverageCheck = _snapDepositState( 403 | * | depositToExecute.createDepositParams.receiver, 404 | * | depositToExecute.createDepositParams.market 405 | | ); 406 | * | _executeDeposit(depositToExecute, marketProps, tokenPrices); 407 | | 408 | | //state after 409 | * | DepositState memory afterDepositExecution = _snapDepositState( 410 | * | depositToExecute.createDepositParams.receiver, 411 | * | depositToExecute.createDepositParams.market 412 | | ); 413 | | 414 | * | depositCreatedArray[randomIndex] = depositCreatedArray[ 415 | * | depositCreatedArray.length - 1 416 | | ]; 417 | * | depositCreatedArray.pop(); 418 | | 419 | * | _checkCoverageAfterDepositExecution( 420 | * | coverageCheck.market, 421 | * | coverageCheck.userBalanceMarket, 422 | * | coverageCheck.marketTotalSupply 423 | | ); 424 | | 425 | * | return (depositToExecute, afterDepositExecution); 426 | | } 427 | | 428 | * | function _executeDeposit( 429 | | DepositCreated memory depositCreated, 430 | | Market.Props memory marketProps, 431 | | TokenPrices memory tokenPrices 432 | * | ) internal { 433 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 434 | * | tokenPrices.tokens, 435 | * | tokenPrices.maxPrices, 436 | * | tokenPrices.minPrices 437 | | ); 438 | | 439 | * | DepositState memory _before = _snapDepositState( 440 | * | depositCreated.depositorParams.user, 441 | * | marketProps.marketToken 442 | | ); 443 | | 444 | * | bytes memory callData_ExecuteDeposit = abi.encodeWithSelector( 445 | * | depositHandler.executeDeposit.selector, 446 | * | depositCreated.key, 447 | * | oracleParams 448 | | ); 449 | * | vm.prank(DEPLOYER); 450 | | 451 | * | ( 452 | * | bool success_ExecuteDeposit, 453 | * | bytes memory returnData_ExecuteDeposit 454 | * | ) = address(depositHandler).call{gas: 30_000_000}( 455 | * | callData_ExecuteDeposit 456 | | ); 457 | | 458 | * | if (!success_ExecuteDeposit) { 459 | * | invariantDoesNotSilentRevert(returnData_ExecuteDeposit); 460 | | } 461 | | 462 | * | DepositState memory _after = _snapDepositState( 463 | * | depositCreated.depositorParams.user, 464 | * | marketProps.marketToken 465 | | ); 466 | | 467 | *r | require( 468 | * | _before.userBalanceMarket < _after.userBalanceMarket, 469 | | "Deposit state was not changed" 470 | | ); 471 | | } 472 | | 473 | * | function _setDepositorParams( 474 | | address user, 475 | | uint256 longAmount, 476 | | uint256 shortAmount, 477 | | bool isWETH 478 | * | ) internal returns (DepositorParams memory) { 479 | * | DepositorParams memory depositorParams = DepositorParams({ 480 | * | user: user, 481 | * | longAmount: longAmount, 482 | * | shortAmount: shortAmount, 483 | * | isWETH: isWETH 484 | | }); 485 | | 486 | * | return depositorParams; 487 | | } 488 | | 489 | * | function _setDepositParams( 490 | | address receiver, 491 | | address callbackContract, 492 | | address uiFeeReceiver, 493 | | address[] memory longTokenSwapPath, 494 | | address[] memory shortTokenSwapPath, 495 | | uint256 minMarketTokens, 496 | | bool shouldUnwrapNativeToken, 497 | | uint256 executionFee, 498 | | uint256 callbackGasLimit 499 | * | ) internal returns (DepositParams memory) { 500 | * | DepositParams memory depositParams = DepositParams({ 501 | * | receiver: receiver, 502 | * | callbackContract: callbackContract, 503 | * | uiFeeReceiver: uiFeeReceiver, 504 | * | longTokenSwapPath: longTokenSwapPath, 505 | * | shortTokenSwapPath: shortTokenSwapPath, 506 | * | minMarketTokens: minMarketTokens, 507 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken, 508 | * | executionFee: executionFee, 509 | * | callbackGasLimit: callbackGasLimit 510 | | }); 511 | | 512 | * | return depositParams; 513 | | } 514 | | 515 | * | function _setDepositParams( 516 | | DepositParams memory depositParams, 517 | | Market.Props memory marketProps 518 | * | ) internal returns (DepositUtils.CreateDepositParams memory) { 519 | * | DepositUtils.CreateDepositParams memory createDepositParams; 520 | * | createDepositParams.receiver = depositParams.receiver; 521 | * | createDepositParams.callbackContract = depositParams.callbackContract; 522 | * | createDepositParams.uiFeeReceiver = depositParams.uiFeeReceiver; 523 | * | createDepositParams.market = marketProps.marketToken; 524 | * | createDepositParams.initialLongToken = marketProps.longToken; 525 | * | createDepositParams.initialShortToken = marketProps.shortToken; 526 | * | createDepositParams.longTokenSwapPath = depositParams.longTokenSwapPath; 527 | * | createDepositParams.shortTokenSwapPath = depositParams 528 | | .shortTokenSwapPath; 529 | * | createDepositParams.minMarketTokens = depositParams.minMarketTokens; 530 | * | createDepositParams.shouldUnwrapNativeToken = depositParams 531 | | .shouldUnwrapNativeToken; 532 | * | createDepositParams.executionFee = depositParams.executionFee; 533 | * | createDepositParams.callbackGasLimit = depositParams.callbackGasLimit; 534 | | 535 | * | return createDepositParams; 536 | | } 537 | | } 538 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/depositSetup/DepositSpeedup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./DepositSetup.sol"; 6 | | 7 | | contract DepositSpeedup is DepositSetup { 8 | *r | function CreateExecuteDeposit( 9 | | uint8 marketIndex, 10 | | uint8 userIndex, 11 | | uint longAmount, 12 | | uint shortAmount, 13 | | uint priceSeed, 14 | | uint executionFee, 15 | | uint8 swapPathSeed 16 | * | ) public { 17 | * | callback.cleanETHBalance(address(0)); 18 | | 19 | * | _createDeposit( 20 | * | marketIndex, 21 | * | userIndex, 22 | * | longAmount, 23 | * | shortAmount, 24 | * | priceSeed, 25 | * | SWAPS_ENABLED ? swapPathSeed : 7, 26 | * | executionFee, 27 | * | false 28 | | ); 29 | * | uint before_callbackBalance_GEN2 = address(callback).balance; 30 | | 31 | * | ( 32 | * | DepositCreated memory depositToExecute, 33 | * | DepositState memory afterDepositExecution 34 | * | ) = ExecuteDeposit(priceSeed, true); //isAtomicExec 35 | | 36 | * | invariantDepositedTokensMatchSimulatedAmounts( 37 | * | depositToExecute, 38 | * | afterDepositExecution 39 | | ); 40 | * | invariantMarketTokenSupplyIncreases(depositToExecute); 41 | | 42 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 43 | | // address(0), 44 | | // before_callbackBalance_GEN2, 45 | | // address(callback).balance, //after 46 | | // depositToExecute.createDepositParams.executionFee 47 | | // ); 48 | | } 49 | | 50 | *r | function CreateCancelDeposit( 51 | | uint8 marketIndex, 52 | | uint8 userIndex, 53 | | uint longAmount, 54 | | uint shortAmount, 55 | | uint priceSeed, 56 | | uint8 swapPathSeed, 57 | | uint executionFee 58 | | ) public { 59 | * | _createDeposit( 60 | * | marketIndex, 61 | * | userIndex, 62 | * | longAmount, 63 | * | shortAmount, 64 | * | priceSeed, 65 | * | SWAPS_ENABLED ? swapPathSeed : 7, 66 | * | executionFee, 67 | * | false 68 | | ); 69 | | 70 | | ( 71 | * | DepositState memory _before, 72 | * | DepositState memory _after, 73 | * | DepositCreated memory depositCreated 74 | * | ) = CancelDeposit(priceSeed, true); 75 | | 76 | | _cancelDepositAssertions(_before, _after, depositCreated); 77 | | } 78 | | function CreateExecuteInitialDeposit( 79 | | uint8 marketIndex, 80 | | uint8 userIndex, 81 | | uint longAmount, 82 | | uint shortAmount, 83 | | uint priceSeed, 84 | | uint8 swapPathSeed, 85 | | uint executionFee 86 | | ) internal { 87 | | callback.cleanETHBalance(address(0)); 88 | | 89 | | _createDeposit( 90 | | marketIndex, 91 | | userIndex, 92 | | longAmount, 93 | | shortAmount, 94 | | priceSeed, 95 | | SWAPS_ENABLED ? swapPathSeed : 7, 96 | | executionFee, 97 | | true //setUp has 0 gas price, so we need to skip fee coverage invariants 98 | | ); 99 | | uint before_callbackBalance_GEN2 = address(callback).balance; 100 | | 101 | | ( 102 | | DepositCreated memory depositToExecute, 103 | | DepositState memory afterDepositExecution 104 | | ) = ExecuteDeposit(priceSeed, true); //isAtomicExec 105 | | 106 | | invariantDepositedTokensMatchSimulatedAmounts( 107 | | depositToExecute, 108 | | afterDepositExecution 109 | | ); 110 | | invariantMarketTokenSupplyIncreases(depositToExecute); 111 | | 112 | | // InvariantExecutionFeeIsAlwaysCovered(//NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 113 | | // address(0), 114 | | // before_callbackBalance_GEN2, 115 | | // address(callback).balance, //after 116 | | // depositToExecute.createDepositParams.executionFee 117 | | // ); 118 | | } 119 | | function setUpDeposits( 120 | | uint8 marketIndex, 121 | | uint longAmount, 122 | | uint shortAmount 123 | | ) internal { 124 | | CreateExecuteInitialDeposit( 125 | | marketIndex, 126 | | 0, 127 | | longAmount, 128 | | shortAmount, 129 | | 5000e4, 130 | | 7, 131 | | FIXED_EXECUTION_FEE_AMOUNT 132 | | ); 133 | | } 134 | | } 135 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/GMXPositionSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./OrderSetup.sol"; 5 | | import "../ADLSetup.sol"; 6 | | 7 | | contract GMXPositionSetup is OrderSetup, ADLSetup { 8 | | using Price for Price.Props; 9 | | OrderCreated[] internal orderCreatedArray; 10 | | 11 | | struct OrderCache { 12 | | address[] longSwapPath; 13 | | address[] swapPath; 14 | | address market; 15 | | address user; 16 | | address token; 17 | | uint decreaseSize; 18 | | uint collateralDeltaAmount; 19 | | bool isLimit; 20 | | bool isLong; 21 | | bool isStopLoss; 22 | | uint priceSeed; 23 | | uint amount; 24 | | uint leverage; 25 | | } 26 | | 27 | *r | function SwapOrder( 28 | | uint8 tokenIndex, 29 | | uint8 userIndex, 30 | | uint priceSeed, 31 | | uint amount, 32 | | uint8 swapPathSeed, 33 | | bool isLimit, 34 | | uint executionFee 35 | * | ) public { 36 | | //Introducing high execution fee, so we can judge by refunded amount after 37 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT; 38 | | 39 | * | OrderCache memory cache; 40 | | 41 | * | cache.user = _getRandomUser(userIndex); 42 | * | cache.swapPath = _getSwapPath(swapPathSeed); 43 | * | cache.token = _getRandomToken(tokenIndex); 44 | | 45 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 46 | * | (amount, ) = _getTokenAmounts( 47 | * | amount, 48 | * | 0, 49 | * | cache.token, 50 | * | address(0), 51 | * | cache.user 52 | | ); 53 | | 54 | * | IBaseOrderUtils.CreateOrderParamsAddresses 55 | * | memory addresses = _setCreateOrderParamsAddresses( 56 | * | cache.user, //receiver, 57 | * | address(callback), //callbackContract 58 | * | address(0), //uiFeeReceiver 59 | * | cache.market, 60 | * | cache.token, 61 | * | cache.swapPath 62 | | ); 63 | | 64 | * | IBaseOrderUtils.CreateOrderParamsNumbers 65 | * | memory numbers = _setCreateOrderParamsNumbers( 66 | * | _getUSDAmount(amount, cache.token, 1, tokenPrices), //sizeDeltaUsd 67 | * | amount, // initialCollateralDeltaAmount, native decimals 68 | * | _getTokenPrice(cache.token, tokenPrices), //triggerPrice 69 | * | 1, //acceptablePrice 70 | * | executionFee, 71 | * | 200 * 1000, //callbackGasLimit 72 | * | 1 // minOutputAmount 73 | | ); 74 | | 75 | * | IBaseOrderUtils.CreateOrderParams 76 | * | memory orderParams = _setCreateOrderParams( 77 | * | addresses, 78 | * | numbers, 79 | * | isLimit 80 | * | ? Order.OrderType.LimitSwap 81 | * | : Order.OrderType.MarketSwap, 82 | * | Order.DecreasePositionSwapType.NoSwap, //hardcoded 83 | * | true, //isLong, any 84 | * | false, //no wrap to simplify assertions 85 | * | true, //auto cancel 86 | * | bytes32(0) //refferal code 87 | | ); 88 | | 89 | * | _order( 90 | * | orderParams, 91 | * | swapPathSeed, 92 | * | tokenPrices, 93 | * | executionFee, 94 | * | keccak256(abi.encode(isLimit ? "SWAP_LIMIT" : "SWAP_MARKET")) 95 | | ); 96 | | 97 | * | ExecuteOrder(priceSeed, true); 98 | | } 99 | | 100 | *r | function IncreaseOrder( 101 | | uint8 marketIndex, 102 | | uint8 userIndex, 103 | | uint leverageSeed, 104 | | uint priceSeed, 105 | | uint amount, 106 | | bool isLimit, 107 | | bool isLong, 108 | | uint8 swapPathSeed, 109 | | uint executionFee 110 | * | ) public { 111 | * | if (!SWAPS_ENABLED) { 112 | * | swapPathSeed = 7; 113 | | } 114 | | 115 | | //Swaps disabled 116 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT; 117 | | 118 | * | OrderCache memory cache; 119 | * | cache.user = _getRandomUser(userIndex); 120 | * | cache.longSwapPath = _getSwapPath(swapPathSeed); 121 | * | cache.market = _getMarketAddress(marketIndex); 122 | * | cache.leverage = clampBetween(leverageSeed, 1, 100); 123 | | 124 | * | if (!_checkMarketForOrders(cache.market)) { 125 | * | return; 126 | | } 127 | | 128 | * | Market.Props memory marketProps = MarketStoreUtils.get( 129 | * | dataStore, 130 | * | cache.market 131 | | ); 132 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 133 | | 134 | * | cache.token = isLong ? marketProps.longToken : marketProps.shortToken; 135 | | 136 | * | if (isLong) { 137 | * | (cache.amount, ) = _getTokenAmounts( 138 | * | amount, 139 | * | 0, 140 | * | marketProps.longToken, 141 | * | marketProps.shortToken, 142 | * | cache.user 143 | | ); 144 | | } else { 145 | * | (, cache.amount) = _getTokenAmounts( 146 | * | 0, 147 | * | amount, 148 | * | marketProps.longToken, 149 | * | marketProps.shortToken, 150 | * | cache.user 151 | | ); 152 | | } 153 | | 154 | * | IBaseOrderUtils.CreateOrderParamsAddresses 155 | * | memory addresses = _setCreateOrderParamsAddresses( 156 | * | cache.user, 157 | * | address(callback), 158 | * | address(0), //uiFeeReceiver 159 | * | cache.market, 160 | * | cache.token, 161 | * | cache.longSwapPath 162 | | ); 163 | | 164 | * | IBaseOrderUtils.CreateOrderParamsNumbers 165 | * | memory numbers = _setCreateOrderParamsNumbers( 166 | * | _getUSDAmount( 167 | * | cache.amount, 168 | * | cache.token, 169 | * | cache.leverage, 170 | * | tokenPrices 171 | | ), 172 | * | cache.amount, // initialCollateralDeltaAmount, native decimals 173 | * | _getTokenPrice(marketProps.indexToken, tokenPrices), //triggerPrice 174 | * | isLong ? type(uint256).max : 1, //acceptable price 175 | * | executionFee, 176 | * | 200 * 1000, //'callbackGasLimit 177 | * | 1 // minOutputAmount 178 | | ); 179 | | 180 | * | IBaseOrderUtils.CreateOrderParams 181 | * | memory orderParams = _setCreateOrderParams( 182 | * | addresses, 183 | * | numbers, 184 | * | isLimit 185 | * | ? Order.OrderType.LimitIncrease 186 | * | : Order.OrderType.MarketIncrease, 187 | * | Order.DecreasePositionSwapType.NoSwap, //hardcoded 188 | * | isLong, //isLong 189 | * | false, //no wrap to simplify assertions 190 | * | true, //auto cancel 191 | * | bytes32(0) //refferal code 192 | | ); 193 | | 194 | * | _order( 195 | * | orderParams, 196 | * | swapPathSeed, 197 | * | tokenPrices, 198 | * | executionFee, 199 | * | keccak256(abi.encode(isLong ? "INCREASE_LONG" : "INCREASE_SHORT")) 200 | | ); 201 | | } 202 | | 203 | * | function DecreasePosition( 204 | | uint8 marketIndex, 205 | | uint8 userIndex, 206 | | uint priceSeed, 207 | | uint collateralDeltaSeed, 208 | | bool closePosition, 209 | | bool isLimit, 210 | | bool isLong, 211 | | bool isStopLoss, 212 | | uint8 swapPathSeed, 213 | | uint executionFee 214 | * | ) public { 215 | * | if (!SWAPS_ENABLED) { 216 | * | swapPathSeed = 7; 217 | | } 218 | | 219 | * | executionFee = FIXED_EXECUTION_FEE_AMOUNT; 220 | | 221 | * | OrderCache memory cache; 222 | * | cache.isLong = isLong; 223 | * | cache.isLimit = isLimit; 224 | * | cache.isStopLoss = isStopLoss; 225 | * | cache.priceSeed = priceSeed; 226 | * | cache.longSwapPath = _getSwapPath(swapPathSeed); 227 | * | cache.market = _getMarketAddress(marketIndex); 228 | * | cache.user = _getRandomUser(userIndex); 229 | | 230 | * | if (!_checkMarketForOrders(cache.market)) { 231 | * | return; 232 | | } 233 | | 234 | * | Market.Props memory marketProps = MarketStoreUtils.get( 235 | * | dataStore, 236 | * | cache.market 237 | | ); 238 | * | TokenPrices memory tokenPrices = _setTokenPrices(cache.priceSeed); 239 | | 240 | * | cache.token = cache.isLong 241 | * | ? marketProps.longToken 242 | * | : marketProps.shortToken; 243 | | 244 | * | bytes32 positionKey = Position.getPositionKey( 245 | * | cache.user, 246 | * | cache.market, 247 | * | cache.token, 248 | * | cache.isLong 249 | | ); 250 | | 251 | * | Position.Props memory position = PositionStoreUtils.get( 252 | * | dataStore, 253 | * | positionKey 254 | | ); 255 | | 256 | * | if ( 257 | * | position.numbers.sizeInUsd == 0 && 258 | * | position.numbers.sizeInTokens == 0 && 259 | * | position.numbers.collateralAmount == 0 260 | | ) { 261 | * | return; 262 | | } 263 | | 264 | * | IBaseOrderUtils.CreateOrderParamsAddresses 265 | * | memory addresses = _setCreateOrderParamsAddresses( 266 | * | cache.user, 267 | * | address(callback), 268 | * | address(0), //uiFeeReceiver 269 | * | cache.market, 270 | * | cache.token, 271 | * | cache.longSwapPath 272 | | ); 273 | | 274 | * | if (closePosition) { 275 | * | cache.decreaseSize = position.numbers.sizeInUsd; 276 | * | cache.collateralDeltaAmount = 0; 277 | | } else { 278 | * | cache.decreaseSize = clampBetween( 279 | * | collateralDeltaSeed, 280 | * | 1, 281 | * | position.numbers.sizeInUsd - 282 | | DECREASE_POSITION_TOLERABLE_PRICE_SUB 283 | | ); 284 | * | cache.collateralDeltaAmount = clampBetween( 285 | * | collateralDeltaSeed / RANDOMIZER_DIVISOR, 286 | * | 1, 287 | * | position.numbers.collateralAmount 288 | | ); 289 | | 290 | *r | require( //The idea is to prevent 0 out if size decrease delta is too small 291 | * | cache.decreaseSize > DECREASE_POSITION_DELTA_MIN, 292 | | "DecreasePosition only by delta amount min" 293 | | ); 294 | | } 295 | | 296 | * | IBaseOrderUtils.CreateOrderParamsNumbers 297 | * | memory numbers = _setCreateOrderParamsNumbers( 298 | * | cache.decreaseSize, 299 | * | cache.collateralDeltaAmount, 300 | * | _getTokenPrice(marketProps.indexToken, tokenPrices), //triggerPrice 301 | * | cache.isLong ? 0 : type(uint256).max, // acceptable price 302 | * | 0, // execution fee 303 | * | 200 * 1000, //'callbackGasLimit 304 | * | 1 // minOutput 305 | | ); 306 | | 307 | * | IBaseOrderUtils.CreateOrderParams 308 | * | memory orderParams = _setCreateOrderParams( 309 | * | addresses, 310 | * | numbers, 311 | * | cache.isStopLoss 312 | * | ? Order.OrderType.StopLossDecrease 313 | * | : cache.isLimit 314 | * | ? Order.OrderType.LimitDecrease 315 | * | : Order.OrderType.MarketDecrease, 316 | * | Order.DecreasePositionSwapType.NoSwap, //hadrcoded 317 | * | cache.isLong, 318 | * | false, //no wrap to simplify assertions 319 | * | true, //auto cancel 320 | * | bytes32(0) //refferal code 321 | | ); 322 | | 323 | * | if (closePosition) { 324 | * | _order( 325 | * | orderParams, 326 | * | swapPathSeed, 327 | * | tokenPrices, 328 | * | 0, 329 | * | keccak256(abi.encode("CLOSE")) 330 | | ); 331 | | } else { 332 | * | _order( 333 | * | orderParams, 334 | * | swapPathSeed, 335 | * | tokenPrices, 336 | * | 0, 337 | * | keccak256(abi.encode("DECREASE")) 338 | | ); 339 | | //Not doing separate handler for stop losses because technically its also a decrease 340 | | } 341 | | } 342 | | 343 | * | function _order( 344 | | IBaseOrderUtils.CreateOrderParams memory params, 345 | | uint8 swapPathSeed, 346 | | TokenPrices memory tokenPrices, 347 | | uint executionFee, 348 | | bytes32 handlerType 349 | * | ) internal returns (OrderCreated memory orderCreated) { 350 | * | if ( 351 | | //Swap Order 352 | * | handlerType == keccak256(abi.encode("SWAP_LIMIT")) || 353 | * | handlerType == keccak256(abi.encode("SWAP_MARKET")) 354 | | ) { 355 | * | _mintAndSendTokensTo( 356 | * | params.addresses.receiver, 357 | * | address(orderVault), //to 358 | * | params.numbers.initialCollateralDeltaAmount, //longTokenAmount 359 | * | 0, //shortTokenAmount 360 | * | params.addresses.initialCollateralToken, //longTokenAddress 361 | * | address(0), //shortTokenAddress 362 | * | executionFee, 363 | * | false //isWETH 364 | | ); 365 | * | } else { 366 | | //Increase and Decrease Order 367 | * | Market.Props memory marketProps = MarketStoreUtils.get( 368 | * | dataStore, 369 | * | params.addresses.market 370 | | ); 371 | | 372 | * | bool isWeth = marketProps.longToken == address(WETH) || 373 | * | marketProps.shortToken == address(WETH); 374 | | 375 | * | uint256 longAmount = params.isLong 376 | * | ? params.numbers.initialCollateralDeltaAmount 377 | * | : 0; 378 | * | uint256 shortAmount = params.isLong 379 | * | ? 0 380 | * | : params.numbers.initialCollateralDeltaAmount; 381 | | 382 | | //Transfer only if Increasing 383 | * | if ( 384 | * | handlerType == 385 | * | keccak256( 386 | * | abi.encode( 387 | * | params.isLong ? "INCREASE_LONG" : "INCREASE_SHORT" 388 | | ) 389 | | ) 390 | | ) { 391 | * | if (params.isLong) { 392 | * | _mintAndSendTokensTo( 393 | * | params.addresses.receiver, 394 | * | address(orderVault), 395 | * | longAmount, 396 | * | shortAmount, 397 | * | marketProps.longToken, 398 | * | address(0), //shortTokenAddress 399 | * | executionFee, 400 | * | isWeth 401 | | ); 402 | | } else { 403 | * | _mintAndSendTokensTo( 404 | * | params.addresses.receiver, 405 | * | address(orderVault), 406 | * | longAmount, 407 | * | shortAmount, 408 | * | address(0), //longTokenAddress 409 | * | marketProps.shortToken, 410 | * | executionFee, 411 | * | isWeth 412 | | ); 413 | | } 414 | | } 415 | | } 416 | | 417 | * | bytes memory callData_CreateOrder = abi.encodeWithSelector( 418 | * | exchangeRouter.createOrder.selector, 419 | * | params 420 | | ); 421 | | 422 | * | vm.prank(params.addresses.receiver); 423 | | 424 | * | ( 425 | * | bool success_CreateOrder, 426 | * | bytes memory returnData_CreateOrder 427 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(callData_CreateOrder); 428 | | 429 | * | if (!success_CreateOrder) { 430 | * | invariantDoesNotSilentRevert(returnData_CreateOrder); 431 | | } else { 432 | * | orderCreated.key = abi.decode(returnData_CreateOrder, (bytes32)); 433 | | } 434 | | 435 | * | orderCreated.createOrderParams = params; 436 | * | orderCreated.updatedAt = block.timestamp; 437 | * | orderCreated.user = params.addresses.receiver; 438 | * | orderCreated.handlerType = handlerType; 439 | * | orderCreated.amountSent = params.numbers.initialCollateralDeltaAmount; 440 | * | orderCreated.isClose = handlerType == keccak256(abi.encode("CLOSE")); 441 | * | orderCreated.swapPathSeed = swapPathSeed; 442 | * | orderCreated.tokenPrices = tokenPrices; 443 | * | orderCreated.executionFee = executionFee; 444 | * | orderCreatedArray.push(orderCreated); 445 | | 446 | * | _checkOrderCreatedCoverage(orderCreated); 447 | | } 448 | | 449 | *r | function CancelOrder( 450 | | uint seed, 451 | | bool isAtomicExec 452 | | ) 453 | | public 454 | | returns ( 455 | * | PositionState memory _before, 456 | * | PositionState memory _after, 457 | * | OrderCreated memory orderToCancel 458 | | ) 459 | | { 460 | *r | require(orderCreatedArray.length > 0, "No orders available to cancel"); 461 | | 462 | * | uint256 randomIndex = isAtomicExec 463 | * | ? orderCreatedArray.length - 1 464 | * | : clampBetween(seed, 0, orderCreatedArray.length - 1); 465 | * | orderToCancel = orderCreatedArray[randomIndex]; 466 | | 467 | * | fl.neq( 468 | * | uint(orderToCancel.key), 469 | * | uint(0), 470 | | "Order key is zero and orderToCancel exists" 471 | | ); 472 | | 473 | * | _before = _snapPositionState(orderToCancel.key, orderToCancel); 474 | | 475 | * | bytes memory callData_CancelOrder = abi.encodeWithSelector( 476 | * | exchangeRouter.cancelOrder.selector, 477 | * | orderToCancel.key 478 | | ); 479 | | 480 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 481 | * | vm.prank(orderToCancel.user); 482 | | 483 | * | ( 484 | * | bool success_CancelOrder, 485 | * | bytes memory returnData_CancelOrder 486 | * | ) = address(exchangeRouter).call{gas: 30_000_000}(callData_CancelOrder); 487 | | 488 | * | if (!success_CancelOrder) { 489 | * | invariantDoesNotSilentRevert(returnData_CancelOrder); 490 | | } 491 | | 492 | | _after = _snapPositionState(orderToCancel.key, orderToCancel); 493 | | 494 | | _checkOrderCancelCoverage(orderToCancel); 495 | | } 496 | | 497 | *r | function ExecuteOrder(uint priceSeed, bool isAtomicExec) public { 498 | * | callback.cleanETHBalance(address(0)); 499 | | 500 | *r | require(orderCreatedArray.length > 0, "No orders available to execute"); 501 | | 502 | * | uint256 randomIndex = isAtomicExec 503 | * | ? orderCreatedArray.length - 1 504 | * | : clampBetween(priceSeed, 0, orderCreatedArray.length - 1); 505 | | 506 | * | OrderCreated memory orderToExecute = orderCreatedArray[randomIndex]; 507 | | 508 | * | Market.Props memory marketProps; 509 | * | bytes32 positionKey; 510 | | 511 | * | if (orderToExecute.createOrderParams.addresses.market != address(0)) { 512 | * | marketProps = MarketStoreUtils.get( 513 | * | dataStore, 514 | * | orderToExecute.createOrderParams.addresses.market 515 | | ); 516 | * | positionKey = Position.getPositionKey( 517 | * | orderToExecute.user, 518 | * | marketProps.marketToken, 519 | * | orderToExecute.createOrderParams.isLong 520 | * | ? marketProps.longToken 521 | * | : marketProps.shortToken, 522 | * | orderToExecute.createOrderParams.isLong 523 | | ); 524 | | } 525 | | 526 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 527 | | 528 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 529 | * | tokenPrices.tokens, 530 | * | tokenPrices.maxPrices, 531 | * | tokenPrices.minPrices 532 | | ); 533 | | 534 | * | uint before_callbackBalance_GEN2 = address(callback).balance; 535 | | 536 | * | if (positionKey != 0) { 537 | | /* 538 | | __ 539 | | <(o )___ 540 | | ( ._> / 541 | | `---' Increase and Decrease Order 542 | | */ 543 | | 544 | * | PositionState memory _before = _snapPositionState( 545 | * | positionKey, 546 | * | orderToExecute 547 | | ); 548 | * | _executeOrderGMX(orderToExecute.key, oracleParams); 549 | * | PositionState memory _after = _snapPositionState( 550 | * | positionKey, 551 | * | orderToExecute 552 | | ); 553 | | 554 | * | Position.Props memory position = PositionStoreUtils.get( 555 | * | dataStore, 556 | * | positionKey 557 | | ); 558 | | 559 | * | if ( 560 | * | orderToExecute.createOrderParams.orderType == 561 | * | Order.OrderType.MarketIncrease || 562 | * | orderToExecute.createOrderParams.orderType == 563 | * | Order.OrderType.LimitIncrease 564 | | ) { 565 | * | if (position.numbers.sizeInUsd != 0) { 566 | | //if position opened 567 | * | checkOrderAndGetCoverage( 568 | * | positionKey, 569 | * | marketProps, 570 | * | tokenPrices, 571 | * | true // isIncreaseOrder 572 | | ); 573 | * | _increaseAssertions(_before, _after, orderToExecute); 574 | | if (isAtomicExec) { 575 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 576 | | // address(0), 577 | | // before_callbackBalance_GEN2, 578 | | // address(callback).balance, //after 579 | | // orderToExecute 580 | | // .createOrderParams 581 | | // .numbers 582 | | // .executionFee 583 | | // ); 584 | | } 585 | | } 586 | | } 587 | | 588 | * | if ( 589 | * | orderToExecute.createOrderParams.orderType == 590 | * | Order.OrderType.MarketDecrease || 591 | * | orderToExecute.createOrderParams.orderType == 592 | * | Order.OrderType.LimitDecrease 593 | | ) { 594 | | if (position.numbers.sizeInUsd != 0) { 595 | | //if not closed 596 | | checkOrderAndGetCoverage( 597 | | positionKey, 598 | | marketProps, 599 | | tokenPrices, 600 | | false // isIncreaseOrder 601 | | ); 602 | | } 603 | | _decreaseAssertions(_before, _after, orderToExecute); 604 | | 605 | | if (isAtomicExec) { 606 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 607 | | // address(0), 608 | | // before_callbackBalance_GEN2, 609 | | // address(callback).balance, //after 610 | | // orderToExecute.createOrderParams.numbers.executionFee 611 | | // ); 612 | | } 613 | | } 614 | * | } else { 615 | | /* 616 | | __ 617 | | <(o )___ 618 | | ( ._> / 619 | | `---' Swap Order 620 | | */ 621 | | 622 | * | SwapState memory _before = _snapSwapState(false, orderToExecute); 623 | * | _executeOrderGMX(orderToExecute.key, oracleParams); 624 | * | SwapState memory _after = _snapSwapState(true, orderToExecute); 625 | | 626 | *r | require( 627 | * | _after.balanceOfOutputToken > _before.balanceOfOutputToken, 628 | | "Swap: state was not changed" 629 | | ); 630 | | 631 | * | _swapAssertions(_before, _after, orderToExecute); 632 | | if (isAtomicExec) { 633 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 634 | | // address(0), 635 | | // before_callbackBalance_GEN2, 636 | | // address(callback).balance, //after 637 | | // orderToExecute.createOrderParams.numbers.executionFee 638 | | // ); 639 | | } 640 | | } 641 | | 642 | * | orderCreatedArray[randomIndex] = orderCreatedArray[ 643 | * | orderCreatedArray.length - 1 644 | | ]; 645 | * | orderCreatedArray.pop(); 646 | | } 647 | * | function _executeOrderGMX( 648 | | bytes32 orderKey, 649 | | OracleUtils.SetPricesParams memory oracleParams 650 | * | ) internal { 651 | * | bytes memory callData_ExecuteOrder = abi.encodeWithSelector( 652 | * | orderHandler.executeOrder.selector, 653 | * | orderKey, 654 | * | oracleParams 655 | | ); 656 | * | vm.prank(DEPLOYER); 657 | | 658 | * | ( 659 | * | bool success_ExecuteOrder, 660 | * | bytes memory returnData_ExecuteOrder 661 | * | ) = address(orderHandler).call{gas: 30_000_000}(callData_ExecuteOrder); 662 | | 663 | * | if (!success_ExecuteOrder) { 664 | * | invariantDoesNotSilentRevert(returnData_ExecuteOrder); 665 | | } 666 | | } 667 | | 668 | | function getOrderKeys( 669 | | uint256 start, 670 | | uint256 end 671 | | ) internal view returns (bytes32[] memory) { 672 | | bytes32 ORDER_LIST_KEY = keccak256(abi.encode("ORDER_LIST")); 673 | | return dataStore.getBytes32ValuesAt(ORDER_LIST_KEY, start, end); 674 | | } 675 | * | function _checkMarketForOrders(address market) internal returns (bool) { 676 | * | return market == market_0_WETH_USDC ? false : true; 677 | | } 678 | | 679 | * | function checkOrderAndGetCoverage( 680 | | bytes32 positionKey, 681 | | Market.Props memory marketProps, 682 | | TokenPrices memory tokenPrices, 683 | | bool isIncreaseOrder 684 | * | ) internal { 685 | * | Position.Props memory position = PositionStoreUtils.get( 686 | * | dataStore, 687 | * | positionKey 688 | | ); 689 | | 690 | * | if (position.numbers.sizeInUsd != 0) { 691 | *r | ReaderUtils.PositionInfo memory positionInfo = reader 692 | | .getPositionInfo( 693 | * | dataStore, 694 | * | referralStorage, 695 | * | positionKey, 696 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 697 | * | 0, // size delta usd = 0 because usePositionSizeAsSizeDeltaUsd is true 698 | * | address(0), 699 | * | true // usePositionSizeAsSizeDeltaUsd 700 | | ); 701 | * | ReaderUtils.MarketInfo memory marketInfo = reader.getMarketInfo( 702 | * | dataStore, 703 | * | _getMarketPrices(marketProps.marketToken, tokenPrices), 704 | * | marketProps.marketToken 705 | | ); 706 | * | if (isIncreaseOrder) { 707 | * | _checkIncreaseOrderAndGetPositionCoverage(position); //position info checked separately 708 | * | _checkIncreaseOrderAndGetPositionInfoCoverage(positionInfo); 709 | * | _checkIncreaseOrderAndGetMarketInfoCoverage(marketInfo); 710 | | } else { 711 | | _checkDecreaseOrderAndGetPositionCoverage(position); 712 | | _checkDecreaseOrderAndGetPositionInfoCoverage(positionInfo); 713 | | _checkDecreaseOrderAndGetMarketInfoCoverage(marketInfo); 714 | | } 715 | | } 716 | | } 717 | * | function _getUSDAmount( 718 | | uint amount, 719 | | address token, 720 | | uint leverage, 721 | | TokenPrices memory tokenPrices 722 | * | ) internal returns (uint result) { 723 | * | if (token == address(USDT) || token == address(USDC)) { 724 | * | result = amount * leverage * 1e24; //NOTE: hardcoded precision 725 | * | } else { 726 | * | uint tokenPrice = _getTokenPrice(token, tokenPrices); 727 | * | result = amount * leverage * tokenPrice; 728 | | } 729 | | } 730 | | } 731 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/GMXPositionSpeedup.sol 1 | | pragma solidity ^0.8.0; 2 | | 3 | | import "./GMXPositionSetup.sol"; 4 | | 5 | | contract GMXPositionSpeedup is GMXPositionSetup { 6 | *r | function IncreaseAndCancelOrder( 7 | | uint8 marketIndex, 8 | | uint8 userIndex, 9 | | uint leverageSeed, 10 | | uint priceSeed, 11 | | uint amount, 12 | | bool isLong, 13 | | uint8 swapPathSeed, 14 | | uint executionFee 15 | | ) public { 16 | * | IncreaseOrder( 17 | * | marketIndex, 18 | * | userIndex, 19 | * | leverageSeed, 20 | * | priceSeed, 21 | * | amount, 22 | * | false, 23 | * | isLong, 24 | * | swapPathSeed, 25 | * | executionFee 26 | | ); 27 | | ( 28 | * | PositionState memory _before, 29 | * | PositionState memory _after, 30 | * | OrderCreated memory orderToCancel 31 | * | ) = CancelOrder(priceSeed, true); 32 | | 33 | | _cancelOrderAssertions(_before, _after, orderToCancel); 34 | | } 35 | | 36 | *r | function DecreaseCloseLongShortOrder( 37 | | uint8 marketIndex, 38 | | uint8 userIndex, 39 | | uint leverageSeed, 40 | | uint priceSeed, 41 | | uint amount, 42 | | uint collateralDeltaSeed, 43 | | bool isLong, 44 | | bool isStopLoss, 45 | | bool closePosition, 46 | | uint8 swapPathSeed, 47 | | uint executionFee 48 | | ) public { 49 | * | IncreaseOrder( 50 | * | marketIndex, 51 | * | userIndex, 52 | * | leverageSeed, 53 | * | priceSeed, 54 | * | amount, 55 | * | false, 56 | * | isLong, 57 | * | swapPathSeed, 58 | * | executionFee 59 | | ); 60 | | 61 | * | ExecuteOrder(priceSeed, true); //last item 62 | | 63 | * | DecreasePosition( 64 | * | marketIndex, 65 | * | userIndex, 66 | * | priceSeed, 67 | * | collateralDeltaSeed, 68 | * | closePosition, 69 | * | false, //isLimit 70 | * | isLong, 71 | * | isStopLoss, 72 | * | swapPathSeed, 73 | * | executionFee 74 | | ); 75 | * | ExecuteOrder(priceSeed, true); //last item 76 | | } 77 | | 78 | *r | function IncreaseExecuteLimitOrder( 79 | | uint8 marketIndex, 80 | | uint8 userIndex, 81 | | uint leverageSeed, 82 | | uint priceSeed, 83 | | uint amount, 84 | | bool isLong, 85 | | uint8 swapPathSeed, 86 | | uint executionFee 87 | | ) public { 88 | * | IncreaseOrder( 89 | * | marketIndex, 90 | * | userIndex, 91 | * | leverageSeed, 92 | * | priceSeed, 93 | * | amount, 94 | * | true, 95 | * | isLong, 96 | * | swapPathSeed, 97 | * | executionFee 98 | | ); //7 is emply swap path 99 | * | ExecuteOrder(priceSeed, true); //last item 100 | | } 101 | | 102 | *r | function DecreaseExecuteLimitOrderLong( 103 | | uint8 marketIndex, 104 | | uint8 userIndex, 105 | | uint leverageSeed, 106 | | uint priceSeed, 107 | | uint amount, 108 | | uint collateralDeltaSeed, 109 | | bool isStopLoss, 110 | | bool closePosition, 111 | | uint8 swapPathSeed, 112 | | uint executionFee 113 | | ) public { 114 | * | IncreaseOrder( 115 | * | marketIndex, 116 | * | userIndex, 117 | * | leverageSeed, 118 | * | priceSeed, 119 | * | amount, 120 | * | false, 121 | * | true, 122 | * | swapPathSeed, 123 | * | executionFee 124 | | ); //7 is emply swap path 125 | * | ExecuteOrder(priceSeed, true); //last item 126 | | 127 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 128 | | 129 | * | DecreasePosition( 130 | * | marketIndex, 131 | * | userIndex, 132 | * | priceSeed, 133 | * | collateralDeltaSeed, 134 | * | closePosition, 135 | * | true, 136 | * | true, 137 | * | isStopLoss, 138 | * | swapPathSeed, //7 is emply swap path 139 | * | executionFee 140 | | ); 141 | | 142 | * | ExecuteOrder(priceSeed, true); //last item 143 | | } 144 | *r | function DecreaseExecuteLimitOrderShort( 145 | | uint8 marketIndex, 146 | | uint8 userIndex, 147 | | uint leverageSeed, 148 | | uint priceSeed, 149 | | uint amount, 150 | | uint collateralDeltaSeed, 151 | | bool isStopLoss, 152 | | bool closePosition, 153 | | uint8 swapPathSeed, 154 | | uint executionFee 155 | | ) public { 156 | * | IncreaseOrder( 157 | * | marketIndex, 158 | * | userIndex, 159 | * | leverageSeed, 160 | * | priceSeed, 161 | * | amount, 162 | * | true, 163 | * | false, 164 | * | swapPathSeed, 165 | * | executionFee 166 | | ); //7 is emply swap path 167 | * | ExecuteOrder(priceSeed, true); //last item 168 | | 169 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 170 | | 171 | * | DecreasePosition( 172 | * | marketIndex, 173 | * | userIndex, 174 | * | priceSeed, 175 | * | collateralDeltaSeed, 176 | * | closePosition, 177 | * | true, 178 | * | false, 179 | * | isStopLoss, 180 | * | swapPathSeed, //7 is emply swap path 181 | * | executionFee 182 | | ); 183 | * | ExecuteOrder(priceSeed, true); //last item 184 | | } 185 | | 186 | *r | function DecreaseExecuteLimitOrderShortWithSwap( 187 | | uint8 marketIndex, 188 | | uint8 userIndex, 189 | | uint leverageSeed, 190 | | uint priceSeed, 191 | | uint amount, 192 | | uint collateralDeltaSeed, 193 | | bool closePosition, 194 | | bool isStopLoss, 195 | | uint8 swapPathSeed, 196 | | uint executionFee 197 | | ) public { 198 | * | IncreaseOrder( 199 | * | marketIndex, 200 | * | userIndex, 201 | * | leverageSeed, 202 | * | priceSeed, 203 | * | amount, 204 | * | true, 205 | * | false, 206 | * | swapPathSeed, 207 | * | executionFee 208 | | ); 209 | * | ExecuteOrder(priceSeed, true); //last item 210 | | 211 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 212 | | 213 | * | DecreasePosition( 214 | * | marketIndex, 215 | * | userIndex, 216 | * | priceSeed, 217 | * | collateralDeltaSeed, 218 | * | closePosition, 219 | * | true, 220 | * | false, 221 | * | isStopLoss, 222 | * | swapPathSeed, 223 | * | executionFee 224 | | ); 225 | * | ExecuteOrder(priceSeed, true); //last item 226 | | } 227 | | 228 | *r | function OrderAndADL( 229 | | uint8 marketIndex, 230 | | uint8 userIndex, 231 | | uint leverageSeed, 232 | | uint priceSeed, 233 | | uint amount, 234 | | bool isLong, 235 | | uint8 swapPathSeed, 236 | | uint executionFee 237 | | ) public { 238 | | //Here we creating specific conditions to cover ADL once, later we check if fuzzer reached this conditions itself 239 | * | IncreaseExecuteLimitOrder( 240 | * | 0, 241 | * | 0, 242 | * | 10, 243 | * | 1000e4, 244 | * | 249e17, //49.99% of weth/weth/usdc market 245 | * | true, 246 | * | swapPathSeed, 247 | * | executionFee 248 | | ); 249 | * | ExecuteADL(0, 999999e4); 250 | | } 251 | | } 252 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/OrderSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | import "../../../contracts/order/BaseOrderUtils.sol"; 3 | | pragma solidity ^0.8.0; 4 | * | contract OrderSetup { 5 | * | function _setCreateOrderParamsAddresses( 6 | | address receiver, 7 | | address callbackContract, 8 | | address uiFeeReceiver, 9 | | address market, 10 | | address initialCollateralToken, 11 | | address[] memory swapPath 12 | | ) 13 | | internal 14 | | pure 15 | * | returns (IBaseOrderUtils.CreateOrderParamsAddresses memory) 16 | | { 17 | * | return 18 | * | IBaseOrderUtils.CreateOrderParamsAddresses({ 19 | * | receiver: receiver, 20 | * | cancellationReceiver: receiver, 21 | * | callbackContract: callbackContract, 22 | * | uiFeeReceiver: uiFeeReceiver, 23 | * | market: market, 24 | * | initialCollateralToken: initialCollateralToken, 25 | * | swapPath: swapPath 26 | | }); 27 | | } 28 | | 29 | * | function _setCreateOrderParamsNumbers( 30 | | uint256 sizeDeltaUsd, 31 | | uint256 initialCollateralDeltaAmount, 32 | | uint256 triggerPrice, 33 | | uint256 acceptablePrice, 34 | | uint256 executionFee, 35 | | uint256 callbackGasLimit, 36 | | uint256 minOutputAmount 37 | * | ) internal pure returns (IBaseOrderUtils.CreateOrderParamsNumbers memory) { 38 | * | return 39 | * | IBaseOrderUtils.CreateOrderParamsNumbers({ 40 | * | sizeDeltaUsd: sizeDeltaUsd, 41 | * | initialCollateralDeltaAmount: initialCollateralDeltaAmount, 42 | * | triggerPrice: triggerPrice, 43 | * | acceptablePrice: acceptablePrice, 44 | * | executionFee: executionFee, 45 | * | callbackGasLimit: callbackGasLimit, 46 | * | minOutputAmount: minOutputAmount 47 | | }); 48 | | } 49 | | 50 | * | function _setCreateOrderParams( 51 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses, 52 | | IBaseOrderUtils.CreateOrderParamsNumbers memory numbers, 53 | | Order.OrderType orderType, 54 | | Order.DecreasePositionSwapType decreasePositionSwapType, 55 | | bool isLong, 56 | | bool shouldUnwrapNativeToken, 57 | | bool autoCancel, 58 | | bytes32 referralCode 59 | * | ) internal pure returns (IBaseOrderUtils.CreateOrderParams memory) { 60 | * | return 61 | * | IBaseOrderUtils.CreateOrderParams({ 62 | * | addresses: addresses, 63 | * | numbers: numbers, 64 | * | orderType: orderType, 65 | * | decreasePositionSwapType: decreasePositionSwapType, 66 | * | isLong: isLong, 67 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken, 68 | * | autoCancel: autoCancel, 69 | * | referralCode: referralCode 70 | | }); 71 | | } 72 | | 73 | | function _setMarketPrices( 74 | | uint256 indexTokenPriceMin, 75 | | uint256 indexTokenPriceMax, 76 | | uint256 longTokenPriceMin, 77 | | uint256 longTokenPriceMax, 78 | | uint256 shortTokenPriceMin, 79 | | uint256 shortTokenPriceMax 80 | | ) internal pure returns (MarketUtils.MarketPrices memory) { 81 | | MarketUtils.MarketPrices memory prices; 82 | | prices.indexTokenPrice = Price.Props( 83 | | indexTokenPriceMin, 84 | | indexTokenPriceMax 85 | | ); 86 | | prices.longTokenPrice = Price.Props( 87 | | longTokenPriceMin, 88 | | longTokenPriceMax 89 | | ); 90 | | prices.shortTokenPrice = Price.Props( 91 | | shortTokenPriceMin, 92 | | shortTokenPriceMax 93 | | ); 94 | | 95 | | return prices; 96 | | } 97 | | } 98 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/PositionSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "./OrderSetup.sol"; 5 | | import "../ADLSetup.sol"; 6 | | 7 | | contract PositionSetup is OrderSetup, ADLSetup { 8 | | using Price for Price.Props; 9 | | 10 | | // Function to generate calldata for both exchanges 11 | * | function generateBothExchangesCalldata( 12 | | uint8 seed, 13 | | bool isCollateralToIndex, 14 | | uint priceSeed, 15 | | uint amount 16 | * | ) internal returns (bytes[] memory) { 17 | * | (address vault, uint leverage, address market, ) = _gamma_getVault( 18 | * | seed 19 | | ); 20 | | 21 | * | Market.Props memory marketProps = MarketStoreUtils.get( 22 | * | dataStore, 23 | * | market 24 | | ); 25 | * | address tokenIn = isCollateralToIndex 26 | | ? marketProps.shortToken 27 | * | : marketProps.indexToken; 28 | | 29 | * | address tokenOut = isCollateralToIndex 30 | | ? marketProps.indexToken 31 | * | : marketProps.shortToken; 32 | | 33 | * | bytes[] memory exchangesData = new bytes[](2); 34 | * | uint256 halfAmount = amount / 2; 35 | * | uint256 remainingAmount = amount - halfAmount; 36 | | 37 | * | exchangesData[0] = constructSwapCalldata( 38 | * | tokenIn, 39 | * | tokenOut, 40 | * | halfAmount, 41 | * | 1, 42 | * | vault 43 | | ); 44 | * | exchangesData[1] = constructGMXCalldata(seed, remainingAmount); 45 | * | return exchangesData; 46 | | } 47 | | 48 | | // Function to generate calldata for a single exchange 49 | * | function generateSingleExchangeCalldata( 50 | | bool onlyParaswap, 51 | | uint8 seed, 52 | | bool isCollateralToIndex, 53 | | uint amount 54 | * | ) internal returns (bytes[] memory) { 55 | * | (address vault, uint leverage, address market, ) = _gamma_getVault( 56 | * | seed 57 | | ); 58 | | 59 | * | Market.Props memory marketProps = MarketStoreUtils.get( 60 | * | dataStore, 61 | * | market 62 | | ); 63 | * | address tokenIn = isCollateralToIndex 64 | * | ? marketProps.shortToken 65 | * | : marketProps.indexToken; 66 | | 67 | * | address tokenOut = isCollateralToIndex 68 | * | ? marketProps.indexToken 69 | * | : marketProps.shortToken; 70 | | 71 | * | bytes[] memory exchangesData = new bytes[](1); 72 | * | if (onlyParaswap) { 73 | | exchangesData[0] = constructSwapCalldata( 74 | | tokenIn, 75 | | tokenOut, 76 | | amount, 77 | | 1, 78 | | vault 79 | | ); 80 | | } else { 81 | * | exchangesData[0] = constructGMXCalldata(seed, amount); 82 | | } 83 | | 84 | * | return exchangesData; 85 | | } 86 | | 87 | * | function generateAcceptablePriceExchangeCalldata( 88 | | bool includeSwap, 89 | | uint8 seed, 90 | | bool isCollateralToIndex, 91 | | uint amount, 92 | | bool isLong 93 | * | ) internal returns (bytes[] memory) { 94 | * | (address vault, uint leverage, address market, ) = _gamma_getVault( 95 | * | seed 96 | | ); 97 | | 98 | * | Market.Props memory marketProps = MarketStoreUtils.get( 99 | * | dataStore, 100 | * | market 101 | | ); 102 | * | address tokenIn = isCollateralToIndex 103 | * | ? marketProps.shortToken 104 | * | : marketProps.indexToken; 105 | | 106 | * | address tokenOut = isCollateralToIndex 107 | * | ? marketProps.indexToken 108 | * | : marketProps.shortToken; 109 | | 110 | * | bytes[] memory exchangesData = new bytes[](2); 111 | | 112 | * | exchangesData[0] = abi.encode(isLong ? type(uint256).max : 5); //long has infinite price, shorts arbitrary small 113 | | 114 | * | if (includeSwap) { 115 | * | exchangesData[1] = constructSwapCalldata( 116 | * | tokenIn, 117 | * | tokenOut, 118 | * | amount, 119 | * | 1, 120 | * | vault 121 | | ); 122 | | } 123 | | 124 | * | return exchangesData; 125 | | } 126 | | 127 | | // Wrapper function to execute the swap 128 | * | function executeSwap( 129 | | address vault, 130 | | address market, 131 | | uint leverage, 132 | | uint priceSeed, 133 | | bytes[] memory exchangesData 134 | * | ) internal { 135 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices( 136 | * | market, 137 | * | priceSeed 138 | | ); 139 | | 140 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData(); 141 | | 142 | * | vm.prank(gammaKeeper); 143 | * | try 144 | * | PerpetualVaultLens(vault).run( 145 | * | true, // isOpen (any) 146 | * | true, // isLong (any) 147 | * | leverage * 1e4, // leverage is 1 148 | * | convertedPrices, 149 | * | exchangesData 150 | | ) 151 | * | { 152 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault) 153 | | .swapProgressData(); 154 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 155 | * | fl.t( 156 | * | swappedBefore == swappedAfter, 157 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey" 158 | | ); 159 | | } 160 | | } catch {} 161 | | } 162 | | 163 | | // Main function 164 | *r | function SwapOrder( 165 | | bool bothExchanges, 166 | | bool onlyParaswap, 167 | | uint8 seed, 168 | | uint priceSeed, 169 | | uint amount 170 | * | ) public { 171 | * | bytes[] memory exchangesData; 172 | * | ( 173 | * | address vault, 174 | * | uint leverage, 175 | * | address market, 176 | * | address gmxUtils 177 | * | ) = _gamma_getVault(seed); 178 | | 179 | *r | require( 180 | * | PerpetualVaultLens(vault).checkForCleanStart(), 181 | | "Previous call was not executed" 182 | | ); 183 | * | bool isCollateralToIndex = priceSeed % 2 == 1; 184 | | 185 | * | bothExchanges = false; //NOTE: PARASWAP EXCLUDED 186 | * | onlyParaswap = false; 187 | | 188 | * | if (bothExchanges) { 189 | | exchangesData = generateBothExchangesCalldata( 190 | | seed, 191 | | isCollateralToIndex, 192 | | priceSeed, 193 | | amount 194 | | ); 195 | | } else { 196 | * | exchangesData = generateSingleExchangeCalldata( 197 | * | onlyParaswap, 198 | * | seed, 199 | * | isCollateralToIndex, 200 | * | amount 201 | | ); 202 | | } 203 | | 204 | * | executeSwap(vault, market, leverage, priceSeed, exchangesData); 205 | | } 206 | *r | function IncreaseOrder(uint8 seed, uint priceSeed, bool isLong) public { 207 | * | ( 208 | * | address vault, 209 | * | uint leverage, 210 | * | address market, 211 | * | address gmxUtils 212 | * | ) = _gamma_getVault(seed); 213 | | 214 | * | IERC20 index = IERC20(PerpetualVault(vault).indexToken()); 215 | | 216 | *r | require( 217 | * | PerpetualVaultLens(vault).checkForCleanStart(), 218 | | "Previous call was not executed" 219 | | ); 220 | | 221 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData(); 222 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices( 223 | * | market, 224 | * | priceSeed 225 | | ); 226 | | 227 | * | bytes[] memory data; 228 | * | if (leverage == 1) { 229 | * | bool bothExchanges = false; //NOTE: PARASWAP EXCLUDED 230 | * | bool onlyParaswap = false; 231 | | 232 | * | if (bothExchanges) { 233 | | data = generateBothExchangesCalldata( 234 | | seed, 235 | | true, //isCollateralToIndex 236 | | priceSeed, 237 | | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault) 238 | | ); 239 | | } else { 240 | * | data = generateSingleExchangeCalldata( 241 | * | onlyParaswap, 242 | * | seed, 243 | * | true, //isCollateralToIndex 244 | * | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault) 245 | | ); 246 | | } 247 | | } else { 248 | * | data = generateAcceptablePriceExchangeCalldata( 249 | * | seed % 2 == 0 ? true : false, //includeSwap rand 250 | * | seed, 251 | * | true, //isCollateralToIndex 252 | * | isLong ? USDC.balanceOf(vault) : index.balanceOf(vault), 253 | * | isLong 254 | | ); 255 | | } 256 | | 257 | * | vm.prank(gammaKeeper); 258 | * | try 259 | * | PerpetualVaultLens(vault).run( 260 | * | true, //isOpen 261 | * | isLong, //isLong 262 | * | leverage * 1e4, //leverage is 1,2,3 263 | * | convertedPrices, // MarketPrices memory prices 264 | * | data 265 | | ) 266 | * | { 267 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault) 268 | | .swapProgressData(); 269 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 270 | * | fl.t( 271 | * | swappedBefore == swappedAfter, 272 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey" 273 | | ); 274 | | } 275 | | } catch { 276 | *r | require(false, "Increase Order Run call failed"); 277 | | } 278 | | } 279 | | 280 | * | function DecreasePosition(uint8 seed, uint priceSeed, bool isLong) public { 281 | * | ( 282 | * | address vault, 283 | * | uint leverage, 284 | * | address market, 285 | * | address gmxUtils 286 | * | ) = _gamma_getVault(seed); 287 | | 288 | * | IERC20 index = IERC20(PerpetualVault(vault).indexToken()); 289 | | 290 | *r | require( 291 | * | PerpetualVaultLens(vault).checkForCleanStart(), 292 | | "Previous call was not executed" 293 | | ); 294 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices( 295 | * | market, 296 | * | priceSeed 297 | | ); 298 | | 299 | * | (, uint256 swappedBefore, ) = PerpetualVault(vault).swapProgressData(); 300 | | 301 | * | bytes[] memory data; 302 | * | if (leverage == 1) { 303 | * | bool bothExchanges = false; //NOTE: PARASWAP EXCLUDED 304 | * | bool onlyParaswap = false; 305 | | 306 | * | if (bothExchanges) { 307 | | data = generateBothExchangesCalldata( 308 | | seed, 309 | | false, //isCollateralToIndex 310 | | priceSeed, 311 | | isLong ? index.balanceOf(vault) : USDC.balanceOf(vault) 312 | | ); //priceSeed is amount seed 313 | | } else { 314 | * | data = generateSingleExchangeCalldata( 315 | * | onlyParaswap, 316 | * | seed, 317 | * | false, //isCollateralToIndex 318 | * | isLong ? index.balanceOf(vault) : USDC.balanceOf(vault) 319 | | ); 320 | | } 321 | | } else { 322 | * | data = new bytes[](2); 323 | | 324 | * | data[0] = abi.encode(isLong ? 5 : type(uint256).max); // inverse when decreasing 325 | | } 326 | * | vm.prank(gammaKeeper); 327 | | 328 | * | try 329 | * | PerpetualVaultLens(vault).run( 330 | * | false, //isOpen 331 | * | isLong, //isLong 332 | * | leverage * 1e4, //any leverage 333 | * | convertedPrices, // MarketPrices memory prices 334 | * | data 335 | | ) 336 | * | { 337 | * | (, uint256 swappedAfter, ) = PerpetualVault(vault) 338 | | .swapProgressData(); 339 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 340 | * | fl.t( 341 | * | swappedBefore == swappedAfter, 342 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey" 343 | | ); 344 | | } 345 | | } catch { 346 | *r | require(false, "DecreasePosition Run call failed"); 347 | | } 348 | | } 349 | | 350 | | struct NextActionPerpsCache { 351 | | IERC20 index; 352 | | address vault; 353 | | uint leverage; 354 | | address market; 355 | | address gmxUtils; 356 | | uint256 swappedBefore; 357 | | uint256 swappedAfter; 358 | | bytes[] data; 359 | | bool bothExchanges; 360 | | bool onlyParaswap; 361 | | bool isCollateralToIndex; 362 | | PerpetualVault.FLOW currentFlow; 363 | | MarketPrices convertedPrices; 364 | | } 365 | | 366 | * | function NextActionPerps(uint8 seed, uint priceSeed) public { 367 | * | NextActionPerpsCache memory cache; 368 | | 369 | * | ( 370 | * | cache.vault, 371 | * | cache.leverage, 372 | * | cache.market, 373 | * | cache.gmxUtils 374 | * | ) = _gamma_getVault(seed); 375 | | 376 | * | cache.index = IERC20(PerpetualVault(cache.vault).indexToken()); 377 | | 378 | * | (, cache.swappedBefore, ) = PerpetualVault(cache.vault) 379 | | .swapProgressData(); 380 | | 381 | * | if (!isNextNoAction(cache.vault)) { 382 | * | if (!isNextFinalize(cache.vault) && !isNextSettle(cache.vault)) { 383 | * | if (isNextWithdraw(cache.vault)) { 384 | * | cache.data = generateAcceptablePriceExchangeCalldata( 385 | * | cache.index.balanceOf(cache.vault) > 0, 386 | * | seed, 387 | * | false, //isCollateralToIndex, false, weth => usdc 388 | * | cache.index.balanceOf(cache.vault), 389 | * | false //short 390 | | ); 391 | * | } else if (cache.leverage == 1) { 392 | * | if (isNextSwap(cache.vault)) { 393 | * | cache.data = generateSingleExchangeCalldata( 394 | * | false, // onlyParaswap, doing gmx 395 | * | seed, 396 | * | false, //isCollateralToIndex, hardcoded 397 | * | cache.index.balanceOf(cache.vault) 398 | | ); 399 | * | } else if (checkNextAction(cache.vault)) { 400 | | //isLong 401 | | 402 | * | cache.bothExchanges = false; //NOTE: PARASWAP EXCLUDED 403 | * | cache.onlyParaswap = false; 404 | | 405 | * | cache.isCollateralToIndex = priceSeed % 3 == 0 406 | * | ? false 407 | * | : true; 408 | * | if (cache.bothExchanges) { 409 | | cache.data = generateBothExchangesCalldata( 410 | | seed, 411 | | cache.isCollateralToIndex, 412 | | priceSeed, 413 | | getPositionCollateral(cache.vault) 414 | | ); 415 | | } else { 416 | * | cache.data = generateSingleExchangeCalldata( 417 | * | cache.onlyParaswap, 418 | * | seed, 419 | * | cache.isCollateralToIndex, 420 | * | getPositionCollateral(cache.vault) 421 | | ); 422 | | } 423 | | 424 | * | cache.currentFlow = PerpetualVault(cache.vault).flow(); 425 | | 426 | * | if (cache.currentFlow == PerpetualVault.FLOW.DEPOSIT) { 427 | * | cache.data = generateSingleExchangeCalldata( 428 | * | false, // onlyParaswap, doing gmx 429 | * | seed, 430 | * | true, //isCollateralToIndex, hardcoded 431 | * | USDC.balanceOf(cache.vault) 432 | | ); 433 | | } 434 | | } else { 435 | * | cache.data = generateAcceptablePriceExchangeCalldata( 436 | * | cache.index.balanceOf(cache.vault) > 0, 437 | * | seed, 438 | * | false, //isCollateralToIndex weth => usdc 439 | * | cache.index.balanceOf(cache.vault), 440 | * | false //short 441 | | ); 442 | | } 443 | | } else { 444 | * | cache.data = generateAcceptablePriceExchangeCalldata( 445 | * | cache.index.balanceOf(cache.vault) > 0, //includeSwap rand 446 | * | seed, 447 | * | false, //isCollateralToIndex WETH => USDC 448 | * | cache.index.balanceOf(cache.vault), 449 | * | checkNextAction(cache.vault) 450 | | ); 451 | | } 452 | | } else { 453 | * | if ( 454 | * | isNextFinalize(cache.vault) && 455 | * | cache.index.balanceOf(address(cache.vault)) > 0 456 | | ) { 457 | * | cache.bothExchanges = true; //NOTE: PARASWAP INCLUDED 458 | * | cache.onlyParaswap = false; 459 | | 460 | * | cache.isCollateralToIndex = false; //hardcoded in a PerpetualVault _runSwap(metadata, false); 461 | | 462 | * | if (cache.bothExchanges) { 463 | * | cache.data = generateBothExchangesCalldata( 464 | * | seed, 465 | * | cache.isCollateralToIndex, 466 | * | priceSeed, 467 | * | cache.index.balanceOf(address(cache.vault)) 468 | | ); 469 | | } else { 470 | | cache.data = generateSingleExchangeCalldata( 471 | | cache.onlyParaswap, 472 | | seed, 473 | | cache.isCollateralToIndex, 474 | | cache.index.balanceOf(address(cache.vault)) 475 | | ); 476 | | } 477 | | } 478 | | } 479 | | } else { 480 | | //NO ACTION branch, will trigger compound 481 | * | if (cache.leverage == 1) { 482 | * | cache.bothExchanges = false; //NOTE: PARASWAP INCLUDED 483 | * | cache.onlyParaswap = false; 484 | | 485 | * | cache.isCollateralToIndex = true; //hardcoded in a PerpetualVault _runSwap(metadata, true); 486 | | 487 | * | if (cache.bothExchanges) { 488 | | cache.data = generateBothExchangesCalldata( 489 | | seed, 490 | | cache.isCollateralToIndex, 491 | | priceSeed, 492 | | USDC.balanceOf(address(cache.vault)) 493 | | ); 494 | | } else { 495 | * | cache.data = generateSingleExchangeCalldata( 496 | * | cache.onlyParaswap, 497 | * | seed, 498 | * | cache.isCollateralToIndex, 499 | * | USDC.balanceOf(address(cache.vault)) 500 | | ); 501 | | } 502 | | } else { 503 | * | cache.data = generateAcceptablePriceExchangeCalldata( 504 | * | false, //we need just an acceptable price in this case 505 | * | seed, 506 | * | false, 507 | * | 0, 508 | * | false 509 | | ); 510 | | } 511 | | } 512 | * | cache.convertedPrices = getConvertedMarketPrices( 513 | * | cache.market, 514 | * | priceSeed 515 | | ); 516 | * | vm.prank(gammaKeeper); 517 | * | try 518 | * | PerpetualVaultLens(cache.vault).runNextAction( 519 | * | cache.convertedPrices, 520 | * | cache.data 521 | | ) 522 | | { 523 | * | (, cache.swappedAfter, ) = PerpetualVault(cache.vault) 524 | | .swapProgressData(); 525 | * | if (PerpetualVault(cache.vault).curPositionKey() != bytes32(0)) { 526 | * | fl.t( 527 | * | cache.swappedBefore == cache.swappedAfter, 528 | | "GAMMA-13: The keeper should never be able to do a DEX swap or a GMX swap (any swap) when there is a nonzero curPositionKey" 529 | | ); 530 | | } 531 | | } catch { 532 | *r | require(false, "Next action run call failed"); 533 | | } 534 | | } 535 | | 536 | * | function ExecuteOrder( 537 | | uint8 seed, 538 | | uint priceSeed, 539 | | bool isAtomicExec 540 | * | ) public { 541 | * | (address vault, , , address gmxUtils) = _gamma_getVault(seed); 542 | | 543 | * | (bytes32 requestKey, , , ) = GmxUtils(payable(gmxUtils)).queue(); 544 | | 545 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 546 | | 547 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 548 | * | tokenPrices.tokens, 549 | * | tokenPrices.maxPrices, 550 | * | tokenPrices.minPrices 551 | | ); 552 | | 553 | * | if (requestKey != 0) { 554 | * | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow(); 555 | * | ( 556 | * | PerpetualVault.NextActionSelector currentAction, 557 | | 558 | * | ) = PerpetualVault(vault).nextAction(); 559 | * | _gammaBefore(); 560 | | 561 | * | if (currentFlow == PerpetualVault.FLOW.DEPOSIT) { 562 | * | _executeOrder(requestKey, oracleParams); 563 | * | _gammaAfter(); 564 | | 565 | * | _invariant_GAMMA_02(vault); 566 | * | _invariant_GAMMA_08(vault, priceSeed); 567 | | } 568 | * | if (currentFlow == PerpetualVault.FLOW.SIGNAL_CHANGE) { 569 | * | _executeOrder(requestKey, oracleParams); 570 | * | _gammaAfter(); 571 | | 572 | * | _invariant_GAMMA_02(vault); 573 | * | _invariant_GAMMA_03(vault); 574 | | } 575 | * | if (currentFlow == PerpetualVault.FLOW.WITHDRAW) { 576 | * | _executeOrder(requestKey, oracleParams); 577 | * | _gammaAfter(); 578 | * | _invariant_GAMMA_02(vault); 579 | | 580 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 581 | * | fl.t( 582 | * | currentFlow == PerpetualVault.FLOW.WITHDRAW, 583 | | "GAMMA-11: If withdraw function is called on a open GMX position, callback should always hit the settle case in the afterOrderExecution and afterOrderCancellation function." 584 | | ); 585 | | } 586 | | } 587 | * | if (currentFlow == PerpetualVault.FLOW.COMPOUND) { 588 | * | _executeOrder(requestKey, oracleParams); 589 | * | _gammaAfter(); 590 | * | _invariant_GAMMA_02(vault); 591 | | } 592 | * | if (currentFlow == PerpetualVault.FLOW.NONE) { 593 | * | _executeOrder(requestKey, oracleParams); 594 | * | _gammaAfter(); 595 | | 596 | * | _invariant_GAMMA_03(vault); 597 | | } 598 | | } else { 599 | *r | require(false, "Execute order failed"); 600 | | } 601 | | 602 | * | logNextAction(vault); 603 | | } 604 | * | function _executeOrder( 605 | | bytes32 requestKey, 606 | | OracleUtils.SetPricesParams memory oracleParams 607 | * | ) internal { 608 | * | bytes memory callData_ExecuteOrder = abi.encodeWithSelector( 609 | * | orderHandler.executeOrder.selector, 610 | * | requestKey, 611 | * | oracleParams 612 | | ); 613 | * | vm.prank(DEPLOYER); 614 | | 615 | * | ( 616 | * | bool success_ExecuteOrder, 617 | * | bytes memory returnData_ExecuteOrder 618 | * | ) = address(orderHandler).call{gas: 30_000_000}(callData_ExecuteOrder); 619 | | } 620 | | 621 | *r | function CancelOrder(uint8 seed, uint priceSeed, bool isAtomicExec) public { 622 | * | (address vault, , , address gmxUtils) = _gamma_getVault(seed); 623 | | 624 | * | (bytes32 requestKey, , , ) = GmxUtils(payable(gmxUtils)).queue(); 625 | | 626 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 627 | | 628 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 629 | * | tokenPrices.tokens, 630 | * | tokenPrices.maxPrices, 631 | * | tokenPrices.minPrices 632 | | ); 633 | | 634 | * | if (requestKey != 0) { 635 | * | PerpetualVault.FLOW currentFlow = PerpetualVault(vault).flow(); 636 | * | ( 637 | * | PerpetualVault.NextActionSelector currentAction, 638 | | 639 | * | ) = PerpetualVault(vault).nextAction(); 640 | * | _gammaBefore(); 641 | | 642 | * | bytes memory callData_CancelOrder = abi.encodeWithSelector( 643 | * | orderHandler.cancelOrder.selector, 644 | * | requestKey 645 | | ); 646 | * | vm.prank(DEPLOYER); 647 | | 648 | * | ( 649 | * | bool success_CancelOrder, 650 | * | bytes memory returnData_CancelOrder 651 | * | ) = address(orderHandler).call{gas: 30_000_000}( 652 | * | callData_CancelOrder 653 | | ); 654 | | 655 | * | if (success_CancelOrder) { 656 | * | if (currentFlow == PerpetualVault.FLOW.WITHDRAW) { 657 | | fl.t( 658 | | currentAction == 659 | | PerpetualVault.NextActionSelector.SETTLE_ACTION, 660 | | "GAMMA-11: If withdraw function is called on a open GMX position, callback should always hit the settle case in the afterOrderExecution and afterOrderCancellation function." 661 | | ); 662 | | } 663 | | } 664 | | } 665 | | } 666 | | } 667 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/positionSetup/PositionSpeedup.sol 1 | | pragma solidity ^0.8.0; 2 | | 3 | | import "./PositionSetup.sol"; 4 | | 5 | | contract PositionSpeedup is PositionSetup {} 6 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/shiftSetup/ShiftSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "../depositSetup/DepositSpeedup.sol"; 5 | | 6 | | contract ShiftSetup is DepositSpeedup {} 7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/shiftSetup/ShiftSpeedup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "./ShiftSetup.sol"; 5 | | 6 | | contract ShiftSpeedup is ShiftSetup {} 7 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/withdrawSetup/WithdrawSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./../PropertiesSetup.sol"; 6 | | import "../../../contracts/withdrawal/WithdrawalUtils.sol"; 7 | | 8 | | contract WithdrawSetup is PropertiesSetup { 9 | | WithdrawalCreated[] internal withdrawalCreatedArray; 10 | | 11 | | /** 12 | | // 13 | | // GAMMA withdrawals 14 | | // 15 | | */ 16 | | 17 | *r | function GammaWithdraw( 18 | | uint8 seed, 19 | | uint8 userSeed, 20 | | uint priceSeed 21 | * | ) public returns (bool success, uint depositAmount, uint timestamp) { 22 | * | DepositInfo memory deposit; 23 | | 24 | * | (withdrawalAssertionInputs.vault, , , ) = _gamma_getVault(seed); 25 | *r | require( 26 | * | PerpetualVaultLens(withdrawalAssertionInputs.vault) 27 | | .checkForCleanStart(), 28 | | "Previous call was not executed" 29 | | ); 30 | * | withdrawalAssertionInputs.user = _getRandomUser(userSeed); 31 | * | withdrawalAssertionInputs.depositId = _getRandomDepositId( 32 | * | seed, 33 | * | withdrawalAssertionInputs.user, 34 | * | withdrawalAssertionInputs.vault 35 | | ); 36 | * | uint256 executionFee = PerpetualVault(withdrawalAssertionInputs.vault) 37 | * | .getExecutionGasLimit(true); 38 | | 39 | * | (depositAmount, , , , timestamp, ) = PerpetualVault( 40 | * | withdrawalAssertionInputs.vault 41 | * | ).depositInfo(withdrawalAssertionInputs.depositId); 42 | | 43 | * | vm.warp( 44 | * | timestamp + 45 | * | PerpetualVault(withdrawalAssertionInputs.vault).lockTime() + 46 | * | 1 47 | | ); //to satisfy < comparison 48 | | //prank inside:) 49 | * | bytes memory returnData; 50 | * | (success, returnData) = _gamma_WithdrawCall( 51 | * | withdrawalAssertionInputs.user, 52 | * | withdrawalAssertionInputs.vault, 53 | * | withdrawalAssertionInputs.depositId, 54 | * | executionFee 55 | | ); 56 | | 57 | * | if (returnData.length > 0) { 58 | * | fl.log( 59 | | "Gamma withdraw return data", 60 | * | abi.decode(returnData, (string)) 61 | | ); 62 | | } 63 | | } 64 | | 65 | | /** 66 | | // 67 | | // GMX withdrawals 68 | | // 69 | | */ 70 | | 71 | | struct WithdrawalCache { 72 | | address[] longSwapPath; 73 | | address[] shortSwapPath; 74 | | address market; 75 | | address user; 76 | | } 77 | | 78 | *r | function WithdrawLP( 79 | | uint8 userIndex, 80 | | uint8 marketIndex, 81 | | uint withdrawalAmountSeed, 82 | | uint priceSeed, 83 | | uint8 swapPathSeed, 84 | | uint executionFee, 85 | | bool isAtomic 86 | | ) public { 87 | * | WithdrawalCache memory cache; 88 | * | executionFee = 0; //In withdrawals, we are not performing an execution fee check because of the implemented method of state change verification 89 | | 90 | * | if (!SWAPS_ENABLED) { 91 | * | swapPathSeed = 7; 92 | | } 93 | | 94 | * | cache.longSwapPath = _getSwapPath(swapPathSeed); 95 | * | cache.shortSwapPath = _getSwapPath( 96 | * | SWAPS_ENABLED ? swapPathSeed / 3 : 7 97 | | ); //another path 98 | | 99 | * | cache.market = _getMarketAddress(marketIndex); 100 | * | Market.Props memory marketProps = MarketStoreUtils.get( 101 | * | dataStore, 102 | * | cache.market 103 | | ); 104 | | 105 | * | cache.user = _getRandomUser(userIndex); 106 | * | uint userBalance = ERC20(cache.market).balanceOf(cache.user); 107 | | 108 | * | WithdrawalUtils.CreateWithdrawalParams 109 | * | memory withdrawalParams = _setCreateWithdrawalParams( 110 | * | cache.user, 111 | * | address(0), 112 | * | address(0), 113 | * | cache.market, 114 | * | cache.longSwapPath, // longTokenSwapPath 115 | * | cache.shortSwapPath, // shortTokenSwapPath 116 | * | 1, //min long token amount 117 | * | 1, //min short token amount 118 | * | false, //unwrap 119 | * | executionFee, 120 | * | 200 * 1000 121 | | ); 122 | | 123 | * | WithdrawalState memory stateBefore = _snapWithdrawalState( 124 | * | cache.user, 125 | * | cache.market 126 | | ); 127 | | 128 | | //Idea is to have bigger value than balance, but not as huge to create lots of empty fuzz runs 129 | * | uint amountToWithdraw = clampBetween( 130 | * | withdrawalAmountSeed, 131 | * | 0, 132 | * | userBalance * 2 133 | | ); 134 | | 135 | * | ( 136 | * | stateBefore.simulateLongTokenAmountWithdrawal, 137 | * | stateBefore.simulateShortTokenAmountWithdrawal 138 | * | ) = _simulateWithdrawalAmount( 139 | * | marketProps, 140 | * | amountToWithdraw, 141 | * | priceSeed, 142 | * | isAtomic 143 | | ); 144 | | 145 | * | WithdrawalCreated memory withdrawalCreated = _withdraw( 146 | * | amountToWithdraw, 147 | * | withdrawalParams 148 | | ); 149 | | 150 | | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal( 151 | | dataStore, 152 | | withdrawalCreated.withdrawalKey 153 | | ); 154 | | 155 | | if (isAtomic) { 156 | | ExecuteAtomicWithdawal( 157 | | withdrawalParams, 158 | | priceSeed, 159 | | cache.user, 160 | | amountToWithdraw 161 | | ); 162 | | _checkExecuteAtomicWithdrawalCoverage(withdrawalProps); 163 | | } else { 164 | | ExecuteWithdrawal(priceSeed, true); 165 | | _checkExecuteWithdrawalCoverage(withdrawalProps); 166 | | } 167 | | 168 | | WithdrawalState memory stateAfter = _snapWithdrawalState( 169 | | cache.user, 170 | | cache.market 171 | | ); 172 | | 173 | | require( 174 | | stateBefore.userBalance > stateAfter.userBalance, 175 | | "Withdrawal state was not changed" 176 | | ); 177 | | 178 | | invariantWithdrawnTokensMatchSimulatedAmounts( 179 | | stateBefore, 180 | | stateAfter, 181 | | withdrawalCreated 182 | | ); 183 | | invariantMarketTokenSupplyDecreases(stateBefore, stateAfter); 184 | | } 185 | | 186 | *r | function CreateWithdrawal( 187 | | uint8 userIndex, 188 | | uint8 marketIndex, 189 | | uint withdrawalAmountSeed 190 | * | ) public { 191 | * | address market = _getMarketAddress(marketIndex); 192 | * | Market.Props memory marketProps = MarketStoreUtils.get( 193 | * | dataStore, 194 | * | market 195 | | ); 196 | | 197 | * | address user = _getRandomUser(userIndex); 198 | * | uint userBalance = ERC20(market).balanceOf(user); //NOTE: not checking if balance != 0, putting it into assertions 199 | | 200 | * | uint amountToWithdraw = clampBetween( 201 | * | withdrawalAmountSeed, 202 | * | 0, 203 | * | userBalance * 2 204 | | ); 205 | | 206 | * | WithdrawalUtils.CreateWithdrawalParams 207 | * | memory withdrawalParams = _setCreateWithdrawalParams( 208 | * | user, 209 | * | address(0), 210 | * | address(0), 211 | * | market, 212 | * | _getSwapPath(7), //currently empty to check exact output token amounts, // longTokenSwapPath 213 | * | _getSwapPath(7), //currently empty to check exact output token amounts, 214 | * | 1, //min long token amount 215 | * | 1, //min short token amount 216 | * | false, //unwrap 217 | * | 0, 218 | * | 200 * 1000 219 | | ); 220 | | 221 | * | WithdrawalCreated memory withdrawalCreated = _withdraw( 222 | * | amountToWithdraw, 223 | * | withdrawalParams 224 | | ); 225 | | 226 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal( 227 | * | dataStore, 228 | * | withdrawalCreated.withdrawalKey 229 | | ); 230 | * | _checkCreateWithdrawalCoverage(withdrawalProps); 231 | | } 232 | | 233 | * | function _withdraw( 234 | | uint amount, 235 | | WithdrawalUtils.CreateWithdrawalParams memory withdrawalParams 236 | * | ) internal returns (WithdrawalCreated memory withdrawalCreated) { 237 | * | address user = withdrawalParams.receiver; 238 | | 239 | * | _mintAndSendTokensTo( 240 | * | user, 241 | * | address(withdrawalVault), 242 | * | withdrawalParams.executionFee, 243 | * | 0, 244 | * | address(WETH), 245 | * | address(0), 246 | * | 0, 247 | * | true 248 | | ); 249 | *r | require( 250 | * | ERC20(withdrawalParams.market).balanceOf(user) > 0, 251 | | "Withdrawal: user has no market tokens" 252 | | ); 253 | | 254 | * | vm.prank(user); 255 | *r | ERC20(withdrawalParams.market).transfer( 256 | * | address(withdrawalVault), 257 | * | amount 258 | | ); 259 | | 260 | * | bytes memory callData_CreateWithdrawal = abi.encodeWithSelector( 261 | * | exchangeRouter.createWithdrawal.selector, 262 | * | withdrawalParams 263 | | ); 264 | * | vm.prank(user); 265 | | 266 | * | ( 267 | * | bool success_CreateWithdrawal, 268 | * | bytes memory returnData_CreateWithdrawal 269 | * | ) = address(exchangeRouter).call{gas: 30_000_000}( 270 | * | callData_CreateWithdrawal 271 | | ); 272 | | 273 | * | bytes32 withdrawalKey; 274 | * | if (!success_CreateWithdrawal) { 275 | * | invariantDoesNotSilentRevert(returnData_CreateWithdrawal); 276 | | } else { 277 | * | withdrawalKey = abi.decode(returnData_CreateWithdrawal, (bytes32)); 278 | | } 279 | | 280 | * | withdrawalCreated.withdrawalParams = withdrawalParams; 281 | * | withdrawalCreated.amount = amount; 282 | * | withdrawalCreated.withdrawalKey = withdrawalKey; 283 | * | withdrawalCreatedArray.push(withdrawalCreated); 284 | | } 285 | | 286 | *r | function ExecuteAtomicWithdawal( 287 | | WithdrawalUtils.CreateWithdrawalParams memory withdrawalParams, 288 | | uint priceSeed, 289 | | address user, 290 | | uint amountToWithdraw 291 | | ) public { 292 | * | Market.Props memory marketProps = MarketStoreUtils.get( 293 | * | dataStore, 294 | * | withdrawalParams.market 295 | | ); 296 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 297 | | 298 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 299 | * | tokenPrices.tokens, 300 | * | tokenPrices.maxPrices, 301 | * | tokenPrices.minPrices 302 | | ); 303 | | 304 | * | _mintAndSendTokensTo( 305 | * | user, 306 | * | address(withdrawalVault), 307 | * | withdrawalParams.executionFee, 308 | * | 0, 309 | * | address(WETH), 310 | * | address(0), 311 | * | 0, 312 | * | true 313 | | ); 314 | * | uint longTokenBalanceBefore = ERC20(marketProps.longToken).balanceOf( 315 | * | withdrawalParams.market 316 | | ); 317 | * | uint shortTokenBalanceBefore = ERC20(marketProps.shortToken).balanceOf( 318 | * | withdrawalParams.market 319 | | ); 320 | | 321 | * | require( 322 | * | ERC20(withdrawalParams.market).balanceOf(user) > 0, 323 | | "AtomicWithdrawal: user has no market tokens" 324 | | ); 325 | | 326 | * | vm.prank(user); 327 | * | ERC20(withdrawalParams.market).transfer( 328 | * | address(withdrawalVault), 329 | * | amountToWithdraw 330 | | ); 331 | | 332 | * | bytes memory callData_ExecuteAtomicWithdrawal = abi.encodeWithSelector( 333 | * | exchangeRouter.executeAtomicWithdrawal.selector, 334 | * | withdrawalParams, 335 | * | oracleParams 336 | | ); 337 | | 338 | * | vm.prank(user); 339 | | 340 | * | ( 341 | * | bool success_ExecuteAtomicWithdrawal, 342 | * | bytes memory returnData_ExecuteAtomicWithdrawal 343 | * | ) = address(exchangeRouter).call{gas: 30_000_000}( 344 | * | callData_ExecuteAtomicWithdrawal 345 | | ); 346 | | 347 | * | if (!success_ExecuteAtomicWithdrawal) { 348 | * | invariantDoesNotSilentRevert(returnData_ExecuteAtomicWithdrawal); 349 | | } 350 | | 351 | | require(longTokenBalanceBefore != 0 || shortTokenBalanceBefore != 0); 352 | | require( 353 | | longTokenBalanceBefore != 0 354 | | ? longTokenBalanceBefore > 355 | | ERC20(marketProps.longToken).balanceOf( 356 | | withdrawalParams.market 357 | | ) 358 | | : shortTokenBalanceBefore > 359 | | ERC20(marketProps.shortToken).balanceOf( 360 | | withdrawalParams.market 361 | | ) 362 | | ); //checking if market address has less tokens after execution == some withdrawal succeed 363 | | } 364 | | 365 | *r | function ExecuteWithdrawal(uint priceSeed, bool isAtomicExec) public { 366 | *r | require( 367 | * | withdrawalCreatedArray.length > 0, 368 | | "No withdrawals available to execute" 369 | | ); 370 | | 371 | * | uint256 randomIndex = isAtomicExec 372 | * | ? withdrawalCreatedArray.length - 1 373 | * | : clampBetween(priceSeed, 0, withdrawalCreatedArray.length - 1); 374 | | 375 | * | WithdrawalCreated memory withdrawalToExecute = withdrawalCreatedArray[ 376 | * | randomIndex 377 | | ]; 378 | * | Market.Props memory marketProps = MarketStoreUtils.get( 379 | * | dataStore, 380 | * | withdrawalToExecute.withdrawalParams.market 381 | | ); 382 | * | TokenPrices memory tokenPrices = _setTokenPrices(priceSeed); 383 | | 384 | * | OracleUtils.SetPricesParams memory oracleParams = SetOraclePrices( 385 | * | tokenPrices.tokens, 386 | * | tokenPrices.maxPrices, 387 | * | tokenPrices.minPrices 388 | | ); 389 | | 390 | * | uint longTokenBalanceBefore = ERC20(marketProps.longToken).balanceOf( 391 | * | withdrawalToExecute.withdrawalParams.market 392 | | ); 393 | * | uint shortTokenBalanceBefore = ERC20(marketProps.shortToken).balanceOf( 394 | * | withdrawalToExecute.withdrawalParams.market 395 | | ); 396 | | 397 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal( 398 | * | dataStore, 399 | * | withdrawalToExecute.withdrawalKey 400 | | ); 401 | | 402 | * | uint userLongTokenBalanceBefore = ERC20(marketProps.longToken) 403 | * | .balanceOf(withdrawalProps.addresses.account); 404 | * | uint userShortTokenBalanceBefore = ERC20(marketProps.shortToken) 405 | * | .balanceOf(withdrawalProps.addresses.account); 406 | | 407 | * | _executeWithdrawal( 408 | * | withdrawalToExecute.withdrawalKey, 409 | * | oracleParams, 410 | * | withdrawalToExecute.withdrawalParams.executionFee, 411 | * | isAtomicExec 412 | | ); 413 | | 414 | * | require(longTokenBalanceBefore != 0 || shortTokenBalanceBefore != 0); 415 | * | require( 416 | * | longTokenBalanceBefore != 0 417 | * | ? longTokenBalanceBefore > 418 | * | ERC20(marketProps.longToken).balanceOf( 419 | * | withdrawalToExecute.withdrawalParams.market 420 | | ) 421 | | : shortTokenBalanceBefore > 422 | | ERC20(marketProps.shortToken).balanceOf( 423 | | withdrawalToExecute.withdrawalParams.market 424 | | ) 425 | | ); //checking if market address has less tokens after execution == some withdrawal succeed 426 | | 427 | * | _checkExecuteAtomicWithdrawalCoverage(withdrawalProps); 428 | | 429 | * | uint userLongTokenBalanceAfter = ERC20(marketProps.longToken).balanceOf( 430 | * | withdrawalProps.addresses.account 431 | | ); 432 | * | uint userShortTokenBalanceAfter = ERC20(marketProps.shortToken) 433 | * | .balanceOf(withdrawalProps.addresses.account); 434 | | 435 | * | fl.gt( 436 | * | userLongTokenBalanceAfter, 437 | * | userLongTokenBalanceBefore, 438 | | "GAMMA-14: if user withdraws they will get non zero amount in return" 439 | | ); 440 | | 441 | * | withdrawalCreatedArray[randomIndex] = withdrawalCreatedArray[ 442 | * | withdrawalCreatedArray.length - 1 443 | | ]; 444 | * | withdrawalCreatedArray.pop(); 445 | | } 446 | *r | function CancelWithdrawal( 447 | | uint seed, 448 | | bool isAtomicExec 449 | | ) 450 | | public 451 | | returns ( 452 | * | WithdrawalState memory _before, 453 | * | WithdrawalState memory _after, 454 | * | WithdrawalCreated memory withdrawalToCancel 455 | | ) 456 | * | { 457 | *r | require( 458 | * | withdrawalCreatedArray.length > 0, 459 | | "No withdrawals available to execute" 460 | | ); 461 | | 462 | * | uint256 randomIndex = isAtomicExec 463 | * | ? withdrawalCreatedArray.length - 1 464 | * | : clampBetween(seed, 0, withdrawalCreatedArray.length - 1); 465 | | 466 | * | withdrawalToCancel = withdrawalCreatedArray[randomIndex]; 467 | | 468 | * | _before = _snapWithdrawalState( 469 | * | withdrawalToCancel.withdrawalParams.receiver, 470 | * | withdrawalToCancel.withdrawalParams.market 471 | | ); 472 | * | Withdrawal.Props memory withdrawalProps = reader.getWithdrawal( 473 | * | dataStore, 474 | * | withdrawalToCancel.withdrawalKey 475 | | ); 476 | | 477 | * | bytes memory callData_CancelWithdrawal = abi.encodeWithSelector( 478 | * | exchangeRouter.cancelWithdrawal.selector, 479 | * | withdrawalToCancel.withdrawalKey 480 | | ); 481 | * | vm.warp(block.timestamp + REQUEST_EXPIRATION_TIME); 482 | | 483 | * | vm.prank(withdrawalToCancel.withdrawalParams.receiver); 484 | | 485 | * | ( 486 | * | bool success_CancelWithdrawal, 487 | * | bytes memory returnData_CancelWithdrawal 488 | * | ) = address(exchangeRouter).call{gas: 30_000_000}( 489 | * | callData_CancelWithdrawal 490 | | ); 491 | | 492 | * | if (!success_CancelWithdrawal) { 493 | * | invariantDoesNotSilentRevert(returnData_CancelWithdrawal); 494 | | } 495 | | 496 | * | _after = _snapWithdrawalState( 497 | * | withdrawalToCancel.withdrawalParams.receiver, 498 | * | withdrawalToCancel.withdrawalParams.market 499 | | ); 500 | | 501 | * | _checkCancelWithdrawalCoverage(withdrawalProps); 502 | | } 503 | | 504 | * | function _executeWithdrawal( 505 | | bytes32 key, 506 | | OracleUtils.SetPricesParams memory oracleParams, 507 | | uint executionFee, 508 | | bool isAtomicExec 509 | * | ) internal { 510 | * | callback.cleanETHBalance(address(0)); 511 | * | uint before_callbackBalance_GEN2 = address(callback).balance; 512 | | 513 | * | vm.prank(DEPLOYER); 514 | *r | withdrawalHandler.executeWithdrawal{gas: 30_000_000}(key, oracleParams); 515 | | if (isAtomicExec) { 516 | | // InvariantExecutionFeeIsAlwaysCovered( //NOTE: this execution fee is checked by callback contract which is not used in GAMMA version 517 | | // address(0), 518 | | // before_callbackBalance_GEN2, 519 | | // address(callback).balance, 520 | | // executionFee 521 | | // ); 522 | | } 523 | | } 524 | | 525 | * | function _simulateWithdrawalAmount( 526 | | Market.Props memory marketProps, 527 | | uint amountToWithdraw, 528 | | uint priceSeed, 529 | | bool isAtomic 530 | | ) 531 | | internal 532 | | returns ( 533 | * | uint simulateLongTokenAmountWithdrawal, 534 | * | uint simulateShortTokenAmountWithdrawal 535 | | ) 536 | | { 537 | * | ( 538 | | simulateLongTokenAmountWithdrawal, 539 | | simulateShortTokenAmountWithdrawal 540 | * | ) = ReaderWithdrawalUtils.getWithdrawalAmountOut( 541 | * | dataStore, 542 | * | marketProps, 543 | * | _getMarketPrices( 544 | * | marketProps.marketToken, 545 | * | _setTokenPrices(priceSeed) 546 | | ), 547 | * | amountToWithdraw, 548 | * | address(0), 549 | * | isAtomic 550 | * | ? ISwapPricingUtils.SwapPricingType.Atomic 551 | * | : ISwapPricingUtils.SwapPricingType.TwoStep 552 | | ); 553 | | } 554 | | 555 | * | function _setCreateWithdrawalParams( 556 | | address receiver, 557 | | address callbackContract, 558 | | address uiFeeReceiver, 559 | | address market, 560 | | address[] memory longTokenSwapPath, 561 | | address[] memory shortTokenSwapPath, 562 | | uint256 minLongTokenAmount, 563 | | uint256 minShortTokenAmount, 564 | | bool shouldUnwrapNativeToken, 565 | | uint256 executionFee, 566 | | uint256 callbackGasLimit 567 | * | ) internal pure returns (WithdrawalUtils.CreateWithdrawalParams memory) { 568 | * | WithdrawalUtils.CreateWithdrawalParams memory params = WithdrawalUtils 569 | | .CreateWithdrawalParams({ 570 | * | receiver: receiver, 571 | * | callbackContract: callbackContract, 572 | * | uiFeeReceiver: uiFeeReceiver, 573 | * | market: market, 574 | * | longTokenSwapPath: longTokenSwapPath, 575 | * | shortTokenSwapPath: shortTokenSwapPath, 576 | * | minLongTokenAmount: minLongTokenAmount, 577 | * | minShortTokenAmount: minShortTokenAmount, 578 | * | shouldUnwrapNativeToken: shouldUnwrapNativeToken, 579 | * | executionFee: executionFee, 580 | * | callbackGasLimit: callbackGasLimit 581 | | }); 582 | | 583 | * | return params; 584 | | } 585 | | } 586 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/helpers/withdrawSetup/WithdrawSpeedup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./WithdrawSetup.sol"; 6 | | 7 | | contract WithdrawSpeedup is WithdrawSetup { 8 | *r | function CreateCancelWithdrawal( 9 | | uint8 userIndex, 10 | | uint8 marketIndex, 11 | | uint withdrawalAmountSeed 12 | * | ) public { 13 | * | CreateWithdrawal(userIndex, marketIndex, withdrawalAmountSeed); 14 | * | ( 15 | * | WithdrawalState memory _before, 16 | * | WithdrawalState memory _after, 17 | * | WithdrawalCreated memory withdrawalToCancel 18 | * | ) = CancelWithdrawal(withdrawalAmountSeed, true); 19 | | 20 | * | _cancelWithdrawalAssertions(_before, _after, withdrawalToCancel); 21 | | } 22 | | } 23 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/interfaces/IMockDex.sol 1 | | pragma solidity ^0.8.0; 2 | | pragma experimental ABIEncoderV2; 3 | | 4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | | 6 | | interface IMockDex { 7 | | /** 8 | | * @param fromToken Address of the source token 9 | | * @param fromAmount Amount of source tokens to be swapped 10 | | * @param toAmount Minimum destination token amount expected out of this swap 11 | | * @param expectedAmount Expected amount of destination tokens without slippage 12 | | * @param beneficiary Beneficiary address 13 | | * 0 then 100% will be transferred to beneficiary. Pass 10000 for 100% 14 | | * @param referrer referral id 15 | | * @param useReduxToken whether to use redux token or not 16 | | * @param path Route to be taken for this swap to take place 17 | | 18 | | */ 19 | | struct SellData { 20 | | address fromToken; 21 | | uint256 fromAmount; 22 | | uint256 toAmount; 23 | | uint256 expectedAmount; 24 | | address payable beneficiary; 25 | | string referrer; 26 | | bool useReduxToken; 27 | | Path[] path; 28 | | } 29 | | 30 | | struct MegaSwapSellData { 31 | | address fromToken; 32 | | uint256 fromAmount; 33 | | uint256 toAmount; 34 | | uint256 expectedAmount; 35 | | address payable beneficiary; 36 | | string referrer; 37 | | bool useReduxToken; 38 | | MegaSwapPath[] path; 39 | | } 40 | | 41 | | struct BuyData { 42 | | address fromToken; 43 | | address toToken; 44 | | uint256 fromAmount; 45 | | uint256 toAmount; 46 | | address payable beneficiary; 47 | | string referrer; 48 | | bool useReduxToken; 49 | | BuyRoute[] route; 50 | | } 51 | | 52 | | struct Route { 53 | | address payable exchange; 54 | | address targetExchange; 55 | | uint percent; 56 | | bytes payload; 57 | | uint256 networkFee; //Network fee is associated with 0xv3 trades 58 | | } 59 | | 60 | | struct MegaSwapPath { 61 | | uint256 fromAmountPercent; 62 | | Path[] path; 63 | | } 64 | | 65 | | struct Path { 66 | | address to; 67 | | uint256 totalNetworkFee; //Network fee is associated with 0xv3 trades 68 | | Route[] routes; 69 | | } 70 | | 71 | | struct BuyRoute { 72 | | address payable exchange; 73 | | address targetExchange; 74 | | uint256 fromAmount; 75 | | uint256 toAmount; 76 | | bytes payload; 77 | | uint256 networkFee; //Network fee is associated with 0xv3 trades 78 | | } 79 | | 80 | | // function getPartnerRegistry() external view returns (address); 81 | | 82 | | // function getWhitelistAddress() external view returns (address); 83 | | 84 | | // function getFeeWallet() external view returns (address); 85 | | 86 | | // function getTokenTransferProxy() external view returns (address); 87 | | 88 | | // function getUniswapProxy() external view returns (address); 89 | | 90 | | // function getVersion() external view returns (string memory); 91 | | 92 | | /** 93 | | * @dev The function which performs the multi path swap. 94 | | */ 95 | | // function multiSwap( 96 | | // SellData calldata data 97 | | // ) external payable returns (uint256); 98 | | 99 | | /** 100 | | * @dev The function which performs the single path buy. 101 | | */ 102 | | // function buy(BuyData calldata data) external payable returns (uint256); 103 | | 104 | | // function swapOnUniswap( 105 | | // uint256 amountIn, 106 | | // uint256 amountOutMin, 107 | | // address[] calldata path, 108 | | // uint8 referrer 109 | | // ) external payable; 110 | | 111 | | // function buyOnUniswap( 112 | | // uint256 amountInMax, 113 | | // uint256 amountOut, 114 | | // address[] calldata path, 115 | | // uint8 referrer 116 | | // ) external payable; 117 | | 118 | | // function buyOnUniswapFork( 119 | | // address factory, 120 | | // bytes32 initCode, 121 | | // uint256 amountInMax, 122 | | // uint256 amountOut, 123 | | // address[] calldata path, 124 | | // uint8 referrer 125 | | // ) external payable; 126 | | 127 | | // function swapOnUniswapFork( 128 | | // address factory, 129 | | // bytes32 initCode, 130 | | // uint256 amountIn, 131 | | // uint256 amountOutMin, 132 | | // address[] calldata path, 133 | | // uint8 referrer 134 | | // ) external payable; 135 | | 136 | | // function simplBuy( 137 | | // address fromToken, 138 | | // address toToken, 139 | | // uint256 fromAmount, 140 | | // uint256 toAmount, 141 | | // address[] memory callees, 142 | | // bytes memory exchangeData, 143 | | // uint256[] memory startIndexes, 144 | | // uint256[] memory values, 145 | | // address payable beneficiary, 146 | | // string memory referrer, 147 | | // bool useReduxToken 148 | | // ) external payable; 149 | | 150 | | // function simpleSwap( 151 | | // address fromToken, 152 | | // address toToken, 153 | | // uint256 fromAmount, 154 | | // uint256 toAmount, 155 | | // uint256 expectedAmount, 156 | | // address[] memory callees, 157 | | // bytes memory exchangeData, 158 | | // uint256[] memory startIndexes, 159 | | // uint256[] memory values, 160 | | // address payable beneficiary, 161 | | // string memory referrer, 162 | | // bool useReduxToken 163 | | // ) external payable returns (uint256 receivedAmount); 164 | | 165 | | /** 166 | | * @dev The function which performs the mega path swap. 167 | | * @param data Data required to perform swap. 168 | | */ 169 | | function megaSwap( 170 | | MegaSwapSellData memory data 171 | | ) external payable returns (uint256); 172 | | } 173 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/ADLCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../properties/BeforeAfter.sol"; 6 | | 7 | | contract ADLCoverage is BeforeAfter {} 8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/DepositCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../properties/BeforeAfter.sol"; 6 | | 7 | | contract DepositCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ CREATE DEPOSIT COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | * | function _checkCreateDepositCoverage( 14 | | address market, 15 | | address longToken, 16 | | address shortToken, 17 | | TokenPrices memory tokenPrices, 18 | | address user, 19 | | uint longAmount, 20 | | uint shortAmount 21 | | ) internal { 22 | * | _logMarketCoverage_CreateDeposit(market); 23 | * | _logTokenCoverage_Long_CreateDeposit( 24 | * | longToken, 25 | | "LongToken", 26 | * | _getTokenPrice(longToken, tokenPrices) 27 | | ); 28 | * | _logTokenCoverage_Short_CreateDeposit( 29 | * | shortToken, 30 | | "ShortToken", 31 | * | _getTokenPrice(shortToken, tokenPrices) 32 | | ); 33 | * | _logUserCoverage_CreateDeposit(user); 34 | * | _logLongAmountCoverage_CreateDeposit(longAmount); 35 | * | _logShortAmountCoverage_CreateDeposit(shortAmount); 36 | | } 37 | | 38 | * | function _logUserCoverage_CreateDeposit(address user) internal { 39 | * | if (user == USER0) { 40 | * | fl.log("User USER0 hit"); 41 | | } 42 | * | if (user == USER1) { 43 | * | fl.log("User USER1 hit"); 44 | | } 45 | * | if (user == USER2) { 46 | * | fl.log("User USER2 hit"); 47 | | } 48 | * | if (user == USER3) { 49 | * | fl.log("User USER3 hit"); 50 | | } 51 | * | if (user == USER4) { 52 | * | fl.log("User USER4 hit"); 53 | | } 54 | * | if (user == USER5) { 55 | * | fl.log("User USER5 hit"); 56 | | } 57 | * | if (user == USER6) { 58 | * | fl.log("User USER6 hit"); 59 | | } 60 | * | if (user == USER7) { 61 | * | fl.log("User USER7 hit"); 62 | | } 63 | * | if (user == USER8) { 64 | * | fl.log("User USER8 hit"); 65 | | } 66 | * | if (user == USER9) { 67 | * | fl.log("User USER9 hit"); 68 | | } 69 | * | if (user == USER10) { 70 | * | fl.log("User USER10 hit"); 71 | | } 72 | * | if (user == USER11) { 73 | * | fl.log("User USER11 hit"); 74 | | } 75 | * | if (user == USER12) { 76 | * | fl.log("User USER12 hit"); 77 | | } 78 | * | if (user == USER13) { 79 | * | fl.log("User USER13 hit"); 80 | | } 81 | | } 82 | | 83 | * | function _logMarketCoverage_CreateDeposit(address market) internal { 84 | * | if (market == market_0_WETH_USDC) { 85 | * | fl.log("Market market_0_WETH_USDC hit"); 86 | | } 87 | | 88 | * | if (market == market_WBTC_WBTC_USDC) { 89 | * | fl.log("Market market_WBTC_WBTC_USDC hit"); 90 | | } 91 | * | if (market == market_WETH_WETH_USDC) { 92 | * | fl.log("Market market_WETH_WETH_USDC hit"); 93 | | } 94 | * | if (market == market_WETH_WETH_USDT) { 95 | * | fl.log("Market market_WETH_WETH_USDT hit"); 96 | | } 97 | | } 98 | | 99 | | // /\_/\ 100 | | // ( o.o ) 101 | | // > ^ < CREATE DEPOSIT: LONGS 102 | | 103 | * | function _logTokenCoverage_Long_CreateDeposit( 104 | | address token, 105 | | string memory tokenType, 106 | | uint256 price 107 | | ) internal { 108 | * | if (token == address(WETH)) { 109 | * | fl.log(string(abi.encodePacked(tokenType, " WETH hit"))); 110 | | 111 | * | _logWETHPriceBucket_Long_CreateDeposit(price, token); 112 | | } 113 | * | if (token == address(WBTC)) { 114 | * | fl.log(string(abi.encodePacked(tokenType, " WBTC hit"))); 115 | | 116 | * | _logWBTCPriceBucket_Long_CreateDeposit(price, token); 117 | | } 118 | * | if (token == address(USDC)) { 119 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit"))); 120 | | } 121 | * | if (token == address(USDT)) { 122 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit"))); 123 | | } 124 | | } 125 | * | function _logLongAmountCoverage_CreateDeposit(uint256 amount) internal { 126 | * | if (amount >= 0 && amount < 1e6) { 127 | | fl.log("LongAmount bucket: 0 to 1e6"); 128 | | } 129 | * | if (amount >= 1e6 && amount < 1e12) { 130 | * | fl.log("LongAmount bucket: 1e6 to 1e12"); 131 | | } 132 | * | if (amount >= 1e12 && amount < 1e18) { 133 | * | fl.log("LongAmount bucket: 1e12 to 1e18"); 134 | | } 135 | * | if (amount >= 1e18 && amount < 1e24) { 136 | * | fl.log("LongAmount bucket: 1e18 to 1e24)"); 137 | | } 138 | * | if (amount >= 1e24) { 139 | | fl.log("LongAmount bucket: 1e4) and above"); 140 | | } 141 | | } 142 | | 143 | * | function _logWETHPriceBucket_Long_CreateDeposit( 144 | | uint256 price, 145 | | address token 146 | | ) internal { 147 | * | if ( 148 | * | price >= WETH_MIN_PRICE && 149 | * | price < 10_000e4 * (10 ** _getPrecision(token)) 150 | | ) { 151 | * | fl.log("WETH price from 1k to 10k was hit"); 152 | | } 153 | * | if ( 154 | * | price >= 10_000e4 * (10 ** _getPrecision(token)) && 155 | * | price < 100_000e4 * (10 ** _getPrecision(token)) 156 | | ) { 157 | * | fl.log("WETH price from 10k to 100k was hit"); 158 | | } 159 | * | if ( 160 | * | price >= 100_000e4 * (10 ** _getPrecision(token)) && 161 | * | price < 300_000e4 * (10 ** _getPrecision(token)) 162 | | ) { 163 | * | fl.log("WETH price from 100k to 300k was hit"); 164 | | } 165 | * | if ( 166 | * | price >= 300_000e4 * (10 ** _getPrecision(token)) && 167 | * | price < 400_000e4 * (10 ** _getPrecision(token)) 168 | | ) { 169 | * | fl.log("WETH price from 300k to 400k was hit"); 170 | | } 171 | * | if ( 172 | * | price >= 400_000e4 * (10 ** _getPrecision(token)) && 173 | * | price < 500_000e4 * (10 ** _getPrecision(token)) 174 | | ) { 175 | * | fl.log("WETH price from 400k to 500k was hit"); 176 | | } 177 | * | if ( 178 | * | price >= 500_000e4 * (10 ** _getPrecision(token)) && 179 | * | price < 600_000e4 * (10 ** _getPrecision(token)) 180 | | ) { 181 | * | fl.log("WETH price from 500k to 600k was hit"); 182 | | } 183 | * | if ( 184 | * | price >= 600_000e4 * (10 ** _getPrecision(token)) && 185 | * | price < 700_000e4 * (10 ** _getPrecision(token)) 186 | | ) { 187 | * | fl.log("WETH price from 600k to 700k was hit"); 188 | | } 189 | * | if ( 190 | * | price >= 700_000e4 * (10 ** _getPrecision(token)) && 191 | * | price < 800_000e4 * (10 ** _getPrecision(token)) 192 | | ) { 193 | * | fl.log("WETH price from 700k to 800k was hit"); 194 | | } 195 | * | if ( 196 | * | price >= 800_000e4 * (10 ** _getPrecision(token)) && 197 | * | price < 900_000e4 * (10 ** _getPrecision(token)) 198 | | ) { 199 | * | fl.log("WETH price from 800k to 900k was hit"); 200 | | } 201 | * | if ( 202 | * | price >= 900_000e4 * (10 ** _getPrecision(token)) && 203 | * | price < WETH_MAX_PRICE * (10 ** _getPrecision(token)) 204 | | ) { 205 | * | fl.log("WETH price from 900k to 1m was hit"); 206 | | } 207 | | } 208 | | 209 | * | function _logWBTCPriceBucket_Long_CreateDeposit( 210 | | uint256 price, 211 | | address token 212 | | ) internal { 213 | * | if ( 214 | * | price >= WBTC_MIN_PRICE && 215 | * | price < 10_000e2 * (10 ** _getPrecision(token)) 216 | | ) { 217 | * | fl.log("WBTC price from 1k to 10k was hit"); 218 | | } 219 | * | if ( 220 | * | price >= 10_000e2 * (10 ** _getPrecision(token)) && 221 | * | price < 100_000e2 * (10 ** _getPrecision(token)) 222 | | ) { 223 | * | fl.log("WBTC price from 10k to 100k was hit"); 224 | | } 225 | * | if ( 226 | * | price >= 100_000e2 * (10 ** _getPrecision(token)) && 227 | * | price < 300_000e2 * (10 ** _getPrecision(token)) 228 | | ) { 229 | * | fl.log("WBTC price from 100k to 300k was hit"); 230 | | } 231 | * | if ( 232 | * | price >= 300_000e2 * (10 ** _getPrecision(token)) && 233 | * | price < 400_000e2 * (10 ** _getPrecision(token)) 234 | | ) { 235 | * | fl.log("WBTC price from 300k to 400k was hit"); 236 | | } 237 | * | if ( 238 | * | price >= 400_000e2 * (10 ** _getPrecision(token)) && 239 | * | price < 500_000e2 * (10 ** _getPrecision(token)) 240 | | ) { 241 | * | fl.log("WBTC price from 400k to 500k was hit"); 242 | | } 243 | * | if ( 244 | * | price >= 500_000e2 * (10 ** _getPrecision(token)) && 245 | * | price < 600_000e2 * (10 ** _getPrecision(token)) 246 | | ) { 247 | * | fl.log("WBTC price from 500k to 600k was hit"); 248 | | } 249 | * | if ( 250 | * | price >= 600_000e2 * (10 ** _getPrecision(token)) && 251 | * | price < 700_000e2 * (10 ** _getPrecision(token)) 252 | | ) { 253 | * | fl.log("WBTC price from 600k to 700k was hit"); 254 | | } 255 | * | if ( 256 | * | price >= 700_000e2 * (10 ** _getPrecision(token)) && 257 | * | price < 800_000e2 * (10 ** _getPrecision(token)) 258 | | ) { 259 | * | fl.log("WBTC price from 700k to 800k was hit"); 260 | | } 261 | * | if ( 262 | * | price >= 800_000e2 * (10 ** _getPrecision(token)) && 263 | * | price < 900_000e2 * (10 ** _getPrecision(token)) 264 | | ) { 265 | * | fl.log("WBTC price from 800k to 900k was hit"); 266 | | } 267 | * | if ( 268 | * | price >= 900_000e2 * (10 ** _getPrecision(token)) && 269 | * | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token)) 270 | | ) { 271 | * | fl.log("WBTC price from 900k to 1m was hit"); 272 | | } 273 | | } 274 | | 275 | | // /\_/\ 276 | | // ( o.o ) 277 | | // > ^ < CREATE DEPOSIT: SHORTS 278 | | 279 | * | function _logTokenCoverage_Short_CreateDeposit( 280 | | address token, 281 | | string memory tokenType, 282 | | uint256 price 283 | | ) internal { 284 | * | if (token == address(WETH)) { 285 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit"))); 286 | | _logWETHPriceBucket_Short_CreateDeposit(price, token); 287 | | } 288 | * | if (token == address(WBTC)) { 289 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit"))); 290 | | _logWBTCPriceBucket_Short_CreateDeposit(price, token); 291 | | } 292 | * | if (token == address(USDC)) { 293 | * | fl.log(string(abi.encodePacked(tokenType, " USDC hit"))); 294 | | } 295 | * | if (token == address(USDT)) { 296 | * | fl.log(string(abi.encodePacked(tokenType, " USDT hit"))); 297 | | } 298 | * | if (token == address(SOL)) { 299 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit"))); 300 | | } 301 | | } 302 | | 303 | * | function _logShortAmountCoverage_CreateDeposit(uint256 amount) internal { 304 | * | if (amount >= 0 && amount < 1e6) { 305 | | fl.log("ShortAmount bucket: 0 to 1e6"); 306 | | } 307 | * | if (amount >= 1e6 && amount < 1e12) { 308 | * | fl.log("ShortAmount bucket: 1e6 to 1e12"); 309 | | } 310 | * | if (amount >= 1e12 && amount < 1e18) { 311 | * | fl.log("ShortAmount bucket: 1e12 to 1e18"); 312 | | } 313 | * | if (amount >= 1e18 && amount < 1e24) { 314 | | fl.log("ShortAmount bucket: 1e18 to 1e24"); 315 | | } 316 | * | if (amount >= 1e24) { 317 | | fl.log("ShortAmount bucket: 1e24 and above"); 318 | | } 319 | | } 320 | | 321 | | function _logWETHPriceBucket_Short_CreateDeposit( 322 | | uint256 price, 323 | | address token 324 | | ) internal { 325 | | if ( 326 | | price >= WETH_MIN_PRICE && 327 | | price < 10_000e4 * (10 ** _getPrecision(token)) 328 | | ) { 329 | | fl.log("WETH price from 1k to 10k was hit"); 330 | | } 331 | | if ( 332 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 333 | | price < 100_000e4 * (10 ** _getPrecision(token)) 334 | | ) { 335 | | fl.log("WETH price from 10k to 100k was hit"); 336 | | } 337 | | if ( 338 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 339 | | price < 300_000e4 * (10 ** _getPrecision(token)) 340 | | ) { 341 | | fl.log("WETH price from 100k to 300k was hit"); 342 | | } 343 | | if ( 344 | | price >= 300_000e4 * (10 ** _getPrecision(token)) && 345 | | price < 400_000e4 * (10 ** _getPrecision(token)) 346 | | ) { 347 | | fl.log("WETH price from 300k to 400k was hit"); 348 | | } 349 | | if ( 350 | | price >= 400_000e4 * (10 ** _getPrecision(token)) && 351 | | price < 500_000e4 * (10 ** _getPrecision(token)) 352 | | ) { 353 | | fl.log("WETH price from 400k to 500k was hit"); 354 | | } 355 | | if ( 356 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 357 | | price < 600_000e4 * (10 ** _getPrecision(token)) 358 | | ) { 359 | | fl.log("WETH price from 500k to 600k was hit"); 360 | | } 361 | | if ( 362 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 363 | | price < 700_000e4 * (10 ** _getPrecision(token)) 364 | | ) { 365 | | fl.log("WETH price from 600k to 700k was hit"); 366 | | } 367 | | if ( 368 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 369 | | price < 800_000e4 * (10 ** _getPrecision(token)) 370 | | ) { 371 | | fl.log("WETH price from 700k to 800k was hit"); 372 | | } 373 | | if ( 374 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 375 | | price < 900_000e4 * (10 ** _getPrecision(token)) 376 | | ) { 377 | | fl.log("WETH price from 800k to 900k was hit"); 378 | | } 379 | | if ( 380 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 381 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token)) 382 | | ) { 383 | | fl.log("WETH price from 900k to 1m was hit"); 384 | | } 385 | | } 386 | | function _logWBTCPriceBucket_Short_CreateDeposit( 387 | | uint256 price, 388 | | address token 389 | | ) internal { 390 | | if ( 391 | | price >= WBTC_MIN_PRICE && 392 | | price < 10_000e2 * (10 ** _getPrecision(token)) 393 | | ) { 394 | | fl.log("WBTC price from 1k to 10k was hit"); 395 | | } 396 | | if ( 397 | | price >= 10_000e2 * (10 ** _getPrecision(token)) && 398 | | price < 100_000e2 * (10 ** _getPrecision(token)) 399 | | ) { 400 | | fl.log("WBTC price from 10k to 100k was hit"); 401 | | } 402 | | if ( 403 | | price >= 100_000e2 * (10 ** _getPrecision(token)) && 404 | | price < 300_000e2 * (10 ** _getPrecision(token)) 405 | | ) { 406 | | fl.log("WBTC price from 100k to 300k was hit"); 407 | | } 408 | | if ( 409 | | price >= 300_000e2 * (10 ** _getPrecision(token)) && 410 | | price < 400_000e2 * (10 ** _getPrecision(token)) 411 | | ) { 412 | | fl.log("WBTC price from 300k to 400k was hit"); 413 | | } 414 | | if ( 415 | | price >= 400_000e2 * (10 ** _getPrecision(token)) && 416 | | price < 500_000e2 * (10 ** _getPrecision(token)) 417 | | ) { 418 | | fl.log("WBTC price from 400k to 500k was hit"); 419 | | } 420 | | if ( 421 | | price >= 500_000e2 * (10 ** _getPrecision(token)) && 422 | | price < 600_000e2 * (10 ** _getPrecision(token)) 423 | | ) { 424 | | fl.log("WBTC price from 500k to 600k was hit"); 425 | | } 426 | | if ( 427 | | price >= 600_000e2 * (10 ** _getPrecision(token)) && 428 | | price < 700_000e2 * (10 ** _getPrecision(token)) 429 | | ) { 430 | | fl.log("WBTC price from 600k to 700k was hit"); 431 | | } 432 | | if ( 433 | | price >= 700_000e2 * (10 ** _getPrecision(token)) && 434 | | price < 800_000e2 * (10 ** _getPrecision(token)) 435 | | ) { 436 | | fl.log("WBTC price from 700k to 800k was hit"); 437 | | } 438 | | if ( 439 | | price >= 800_000e2 * (10 ** _getPrecision(token)) && 440 | | price < 900_000e2 * (10 ** _getPrecision(token)) 441 | | ) { 442 | | fl.log("WBTC price from 800k to 900k was hit"); 443 | | } 444 | | if ( 445 | | price >= 900_000e2 * (10 ** _getPrecision(token)) && 446 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token)) 447 | | ) { 448 | | fl.log("WBTC price from 900k to 1m was hit"); 449 | | } 450 | | } 451 | | 452 | | function _logSOLPriceBucket_Short_CreateDeposit( 453 | | uint256 price, 454 | | address token 455 | | ) internal { 456 | | if ( 457 | | price >= SOL_MIN_PRICE && 458 | | price < 100e4 * (10 ** _getPrecision(token)) 459 | | ) { 460 | | fl.log("SOL price from 1 to 100 was hit"); 461 | | } 462 | | if ( 463 | | price >= 1000e4 * (10 ** _getPrecision(token)) && 464 | | price < 10_000e4 * (10 ** _getPrecision(token)) 465 | | ) { 466 | | fl.log("SOL price from 1k to 10k was hit"); 467 | | } 468 | | if ( 469 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 470 | | price < 100_000e4 * (10 ** _getPrecision(token)) 471 | | ) { 472 | | fl.log("SOL price from 10k to 100k was hit"); 473 | | } 474 | | if ( 475 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 476 | | price < 200_000e4 * (10 ** _getPrecision(token)) 477 | | ) { 478 | | fl.log("SOL price from 100k to 200k was hit"); 479 | | } 480 | | if ( 481 | | price >= 200_000e4 * (10 ** _getPrecision(token)) && 482 | | price < 500_000e4 * (10 ** _getPrecision(token)) 483 | | ) { 484 | | fl.log("SOL price from 200k to 500k was hit"); 485 | | } 486 | | if ( 487 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 488 | | price < 600_000e4 * (10 ** _getPrecision(token)) 489 | | ) { 490 | | fl.log("SOL price from 500k to 600k was hit"); 491 | | } 492 | | if ( 493 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 494 | | price < 700_000e4 * (10 ** _getPrecision(token)) 495 | | ) { 496 | | fl.log("SOL price from 600k to 700k was hit"); 497 | | } 498 | | if ( 499 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 500 | | price < 800_000e4 * (10 ** _getPrecision(token)) 501 | | ) { 502 | | fl.log("SOL price from 700k to 800k was hit"); 503 | | } 504 | | if ( 505 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 506 | | price < 900_000e4 * (10 ** _getPrecision(token)) 507 | | ) { 508 | | fl.log("SOL price from 800k to 900k was hit"); 509 | | } 510 | | if ( 511 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 512 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token)) 513 | | ) { 514 | | fl.log("SOL price from 900k to 1m was hit"); 515 | | } 516 | | } 517 | | 518 | | // /\_/\ ___ 519 | | // = o_o =_______ \ \ CANCEL DEPOSIT COVERAGE 520 | | // __^ __( \.__) ) 521 | | // (@)<_____>__(_____)____/ 522 | | 523 | | function _checkCancelDepositCoverage( 524 | | address market, 525 | | address longToken, 526 | | address shortToken, 527 | | TokenPrices memory tokenPrices, 528 | | address user, 529 | | uint longAmount, 530 | | uint shortAmount 531 | | ) internal { 532 | | _logMarketCoverage_CancelDeposit(market); 533 | | _logTokenCoverage_Long_CancelDeposit( 534 | | longToken, 535 | | "LongToken", 536 | | _getTokenPrice(longToken, tokenPrices) 537 | | ); 538 | | _logTokenCoverage_Short_CancelDeposit( 539 | | shortToken, 540 | | "ShortToken", 541 | | _getTokenPrice(shortToken, tokenPrices) 542 | | ); 543 | | _logUserCoverage_CancelDeposit(user); 544 | | _logLongAmountCoverage_CancelDeposit(longAmount); 545 | | _logShortAmountCoverage_CancelDeposit(shortAmount); 546 | | } 547 | | 548 | | function _logUserCoverage_CancelDeposit(address user) internal { 549 | | if (user == USER0) { 550 | | fl.log("User USER0 hit"); 551 | | } 552 | | if (user == USER1) { 553 | | fl.log("User USER1 hit"); 554 | | } 555 | | if (user == USER2) { 556 | | fl.log("User USER2 hit"); 557 | | } 558 | | if (user == USER3) { 559 | | fl.log("User USER3 hit"); 560 | | } 561 | | if (user == USER4) { 562 | | fl.log("User USER4 hit"); 563 | | } 564 | | if (user == USER5) { 565 | | fl.log("User USER5 hit"); 566 | | } 567 | | if (user == USER6) { 568 | | fl.log("User USER6 hit"); 569 | | } 570 | | if (user == USER7) { 571 | | fl.log("User USER7 hit"); 572 | | } 573 | | if (user == USER8) { 574 | | fl.log("User USER8 hit"); 575 | | } 576 | | if (user == USER9) { 577 | | fl.log("User USER9 hit"); 578 | | } 579 | | if (user == USER10) { 580 | | fl.log("User USER10 hit"); 581 | | } 582 | | if (user == USER11) { 583 | | fl.log("User USER11 hit"); 584 | | } 585 | | if (user == USER12) { 586 | | fl.log("User USER12 hit"); 587 | | } 588 | | if (user == USER13) { 589 | | fl.log("User USER13 hit"); 590 | | } 591 | | } 592 | | 593 | | function _logMarketCoverage_CancelDeposit(address market) internal { 594 | | if (market == market_0_WETH_USDC) { 595 | | fl.log("Market market_0_WETH_USDC hit"); 596 | | } 597 | | 598 | | if (market == market_WBTC_WBTC_USDC) { 599 | | fl.log("Market market_WBTC_WBTC_USDC hit"); 600 | | } 601 | | if (market == market_WETH_WETH_USDC) { 602 | | fl.log("Market market_WETH_WETH_USDC hit"); 603 | | } 604 | | if (market == market_WETH_WETH_USDT) { 605 | | fl.log("Market market_WETH_WETH_USDT hit"); 606 | | } 607 | | } 608 | | 609 | | // /\_/\ 610 | | // ( o.o ) 611 | | // > ^ < CANCEL DEPOSIT: LONGS 612 | | 613 | | function _logTokenCoverage_Long_CancelDeposit( 614 | | address token, 615 | | string memory tokenType, 616 | | uint256 price 617 | | ) internal { 618 | | if (token == address(WETH)) { 619 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit"))); 620 | | _logWETHPriceBucket_Long_CancelDeposit(price, token); 621 | | } 622 | | if (token == address(WBTC)) { 623 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit"))); 624 | | _logWBTCPriceBucket_Long_CancelDeposit(price, token); 625 | | } 626 | | if (token == address(USDC)) { 627 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit"))); 628 | | } 629 | | if (token == address(USDT)) { 630 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit"))); 631 | | } 632 | | 633 | | if (token == address(SOL)) { 634 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit"))); 635 | | _logSOLPriceBucket_Long_CancelDeposit(price, token); 636 | | } 637 | | } 638 | | 639 | | function _logLongAmountCoverage_CancelDeposit(uint256 amount) internal { 640 | | if (amount >= 0 && amount < 1e6) { 641 | | fl.log("LongAmount bucket: 0 to 1e6"); 642 | | } 643 | | if (amount >= 1e6 && amount < 1e12) { 644 | | fl.log("LongAmount bucket: 1e6 to 1e12"); 645 | | } 646 | | if (amount >= 1e12 && amount < 1e18) { 647 | | fl.log("LongAmount bucket: 1e12 to 1e18"); 648 | | } 649 | | if (amount >= 1e18 && amount < 1e24) { 650 | | fl.log("LongAmount bucket: 1e18 to 1e24)"); 651 | | } 652 | | if (amount >= 1e24) { 653 | | fl.log("LongAmount bucket: 1e4) and above"); 654 | | } 655 | | } 656 | | 657 | | function _logWETHPriceBucket_Long_CancelDeposit( 658 | | uint256 price, 659 | | address token 660 | | ) internal { 661 | | if ( 662 | | price >= WETH_MIN_PRICE && 663 | | price < 10_000e4 * (10 ** _getPrecision(token)) 664 | | ) { 665 | | fl.log("WETH price from 1k to 10k was hit"); 666 | | } 667 | | if ( 668 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 669 | | price < 100_000e4 * (10 ** _getPrecision(token)) 670 | | ) { 671 | | fl.log("WETH price from 10k to 100k was hit"); 672 | | } 673 | | if ( 674 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 675 | | price < 300_000e4 * (10 ** _getPrecision(token)) 676 | | ) { 677 | | fl.log("WETH price from 100k to 300k was hit"); 678 | | } 679 | | if ( 680 | | price >= 300_000e4 * (10 ** _getPrecision(token)) && 681 | | price < 400_000e4 * (10 ** _getPrecision(token)) 682 | | ) { 683 | | fl.log("WETH price from 300k to 400k was hit"); 684 | | } 685 | | if ( 686 | | price >= 400_000e4 * (10 ** _getPrecision(token)) && 687 | | price < 500_000e4 * (10 ** _getPrecision(token)) 688 | | ) { 689 | | fl.log("WETH price from 400k to 500k was hit"); 690 | | } 691 | | if ( 692 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 693 | | price < 600_000e4 * (10 ** _getPrecision(token)) 694 | | ) { 695 | | fl.log("WETH price from 500k to 600k was hit"); 696 | | } 697 | | if ( 698 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 699 | | price < 700_000e4 * (10 ** _getPrecision(token)) 700 | | ) { 701 | | fl.log("WETH price from 600k to 700k was hit"); 702 | | } 703 | | if ( 704 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 705 | | price < 800_000e4 * (10 ** _getPrecision(token)) 706 | | ) { 707 | | fl.log("WETH price from 700k to 800k was hit"); 708 | | } 709 | | if ( 710 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 711 | | price < 900_000e4 * (10 ** _getPrecision(token)) 712 | | ) { 713 | | fl.log("WETH price from 800k to 900k was hit"); 714 | | } 715 | | if ( 716 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 717 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token)) 718 | | ) { 719 | | fl.log("WETH price from 900k to 1m was hit"); 720 | | } 721 | | } 722 | | function _logWBTCPriceBucket_Long_CancelDeposit( 723 | | uint256 price, 724 | | address token 725 | | ) internal { 726 | | if ( 727 | | price >= WBTC_MIN_PRICE && 728 | | price < 10_000e2 * (10 ** _getPrecision(token)) 729 | | ) { 730 | | fl.log("WBTC price from 1k to 10k was hit"); 731 | | } 732 | | if ( 733 | | price >= 10_000e2 * (10 ** _getPrecision(token)) && 734 | | price < 100_000e2 * (10 ** _getPrecision(token)) 735 | | ) { 736 | | fl.log("WBTC price from 10k to 100k was hit"); 737 | | } 738 | | if ( 739 | | price >= 100_000e2 * (10 ** _getPrecision(token)) && 740 | | price < 300_000e2 * (10 ** _getPrecision(token)) 741 | | ) { 742 | | fl.log("WBTC price from 100k to 300k was hit"); 743 | | } 744 | | if ( 745 | | price >= 300_000e2 * (10 ** _getPrecision(token)) && 746 | | price < 400_000e2 * (10 ** _getPrecision(token)) 747 | | ) { 748 | | fl.log("WBTC price from 300k to 400k was hit"); 749 | | } 750 | | if ( 751 | | price >= 400_000e2 * (10 ** _getPrecision(token)) && 752 | | price < 500_000e2 * (10 ** _getPrecision(token)) 753 | | ) { 754 | | fl.log("WBTC price from 400k to 500k was hit"); 755 | | } 756 | | if ( 757 | | price >= 500_000e2 * (10 ** _getPrecision(token)) && 758 | | price < 600_000e2 * (10 ** _getPrecision(token)) 759 | | ) { 760 | | fl.log("WBTC price from 500k to 600k was hit"); 761 | | } 762 | | if ( 763 | | price >= 600_000e2 * (10 ** _getPrecision(token)) && 764 | | price < 700_000e2 * (10 ** _getPrecision(token)) 765 | | ) { 766 | | fl.log("WBTC price from 600k to 700k was hit"); 767 | | } 768 | | if ( 769 | | price >= 700_000e2 * (10 ** _getPrecision(token)) && 770 | | price < 800_000e2 * (10 ** _getPrecision(token)) 771 | | ) { 772 | | fl.log("WBTC price from 700k to 800k was hit"); 773 | | } 774 | | if ( 775 | | price >= 800_000e2 * (10 ** _getPrecision(token)) && 776 | | price < 900_000e2 * (10 ** _getPrecision(token)) 777 | | ) { 778 | | fl.log("WBTC price from 800k to 900k was hit"); 779 | | } 780 | | if ( 781 | | price >= 900_000e2 * (10 ** _getPrecision(token)) && 782 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token)) 783 | | ) { 784 | | fl.log("WBTC price from 900k to 1m was hit"); 785 | | } 786 | | } 787 | | function _logSOLPriceBucket_Long_CancelDeposit( 788 | | uint256 price, 789 | | address token 790 | | ) internal { 791 | | if ( 792 | | price >= SOL_MIN_PRICE && 793 | | price < 100e4 * (10 ** _getPrecision(token)) 794 | | ) { 795 | | fl.log("SOL price from 1 to 100 was hit"); 796 | | } 797 | | if ( 798 | | price >= 1000e4 * (10 ** _getPrecision(token)) && 799 | | price < 10_000e4 * (10 ** _getPrecision(token)) 800 | | ) { 801 | | fl.log("SOL price from 1k to 10k was hit"); 802 | | } 803 | | if ( 804 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 805 | | price < 100_000e4 * (10 ** _getPrecision(token)) 806 | | ) { 807 | | fl.log("SOL price from 10k to 100k was hit"); 808 | | } 809 | | if ( 810 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 811 | | price < 200_000e4 * (10 ** _getPrecision(token)) 812 | | ) { 813 | | fl.log("SOL price from 100k to 200k was hit"); 814 | | } 815 | | if ( 816 | | price >= 200_000e4 * (10 ** _getPrecision(token)) && 817 | | price < 500_000e4 * (10 ** _getPrecision(token)) 818 | | ) { 819 | | fl.log("SOL price from 200k to 500k was hit"); 820 | | } 821 | | if ( 822 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 823 | | price < 600_000e4 * (10 ** _getPrecision(token)) 824 | | ) { 825 | | fl.log("SOL price from 500k to 600k was hit"); 826 | | } 827 | | if ( 828 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 829 | | price < 700_000e4 * (10 ** _getPrecision(token)) 830 | | ) { 831 | | fl.log("SOL price from 600k to 700k was hit"); 832 | | } 833 | | if ( 834 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 835 | | price < 800_000e4 * (10 ** _getPrecision(token)) 836 | | ) { 837 | | fl.log("SOL price from 700k to 800k was hit"); 838 | | } 839 | | if ( 840 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 841 | | price < 900_000e4 * (10 ** _getPrecision(token)) 842 | | ) { 843 | | fl.log("SOL price from 800k to 900k was hit"); 844 | | } 845 | | if ( 846 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 847 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token)) 848 | | ) { 849 | | fl.log("SOL price from 900k to 1m was hit"); 850 | | } 851 | | } 852 | | 853 | | // /\_/\ 854 | | // ( o.o ) 855 | | // > ^ < CANCEL DEPOSIT: SHORTS 856 | | 857 | | function _logTokenCoverage_Short_CancelDeposit( 858 | | address token, 859 | | string memory tokenType, 860 | | uint256 price 861 | | ) internal { 862 | | if (token == address(WETH)) { 863 | | fl.log(string(abi.encodePacked(tokenType, " WETH hit"))); 864 | | _logWETHPriceBucket_Short_CancelDeposit(price, token); 865 | | } 866 | | if (token == address(WBTC)) { 867 | | fl.log(string(abi.encodePacked(tokenType, " WBTC hit"))); 868 | | _logWBTCPriceBucket_Short_CancelDeposit(price, token); 869 | | } 870 | | if (token == address(USDC)) { 871 | | fl.log(string(abi.encodePacked(tokenType, " USDC hit"))); 872 | | } 873 | | if (token == address(USDT)) { 874 | | fl.log(string(abi.encodePacked(tokenType, " USDT hit"))); 875 | | } 876 | | if (token == address(SOL)) { 877 | | fl.log(string(abi.encodePacked(tokenType, " SOL hit"))); 878 | | _logSOLPriceBucket_Short_CancelDeposit(price, token); 879 | | } 880 | | } 881 | | 882 | | function _logShortAmountCoverage_CancelDeposit(uint256 amount) internal { 883 | | if (amount >= 0 && amount < 1e6) { 884 | | fl.log("ShortAmount bucket: 0 to 1e6"); 885 | | } 886 | | if (amount >= 1e6 && amount < 1e12) { 887 | | fl.log("ShortAmount bucket: 1e6 to 1e12"); 888 | | } 889 | | if (amount >= 1e12 && amount < 1e18) { 890 | | fl.log("ShortAmount bucket: 1e12 to 1e18"); 891 | | } 892 | | if (amount >= 1e18 && amount < 1e24) { 893 | | fl.log("ShortAmount bucket: 1e18 to 1e24"); 894 | | } 895 | | if (amount >= 1e24) { 896 | | fl.log("ShortAmount bucket: 1e24 and above"); 897 | | } 898 | | } 899 | | 900 | | function _logWETHPriceBucket_Short_CancelDeposit( 901 | | uint256 price, 902 | | address token 903 | | ) internal { 904 | | if ( 905 | | price >= WETH_MIN_PRICE && 906 | | price < 10_000e4 * (10 ** _getPrecision(token)) 907 | | ) { 908 | | fl.log("WETH price from 1k to 10k was hit"); 909 | | } 910 | | if ( 911 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 912 | | price < 100_000e4 * (10 ** _getPrecision(token)) 913 | | ) { 914 | | fl.log("WETH price from 10k to 100k was hit"); 915 | | } 916 | | if ( 917 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 918 | | price < 300_000e4 * (10 ** _getPrecision(token)) 919 | | ) { 920 | | fl.log("WETH price from 100k to 300k was hit"); 921 | | } 922 | | if ( 923 | | price >= 300_000e4 * (10 ** _getPrecision(token)) && 924 | | price < 400_000e4 * (10 ** _getPrecision(token)) 925 | | ) { 926 | | fl.log("WETH price from 300k to 400k was hit"); 927 | | } 928 | | if ( 929 | | price >= 400_000e4 * (10 ** _getPrecision(token)) && 930 | | price < 500_000e4 * (10 ** _getPrecision(token)) 931 | | ) { 932 | | fl.log("WETH price from 400k to 500k was hit"); 933 | | } 934 | | if ( 935 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 936 | | price < 600_000e4 * (10 ** _getPrecision(token)) 937 | | ) { 938 | | fl.log("WETH price from 500k to 600k was hit"); 939 | | } 940 | | if ( 941 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 942 | | price < 700_000e4 * (10 ** _getPrecision(token)) 943 | | ) { 944 | | fl.log("WETH price from 600k to 700k was hit"); 945 | | } 946 | | if ( 947 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 948 | | price < 800_000e4 * (10 ** _getPrecision(token)) 949 | | ) { 950 | | fl.log("WETH price from 700k to 800k was hit"); 951 | | } 952 | | if ( 953 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 954 | | price < 900_000e4 * (10 ** _getPrecision(token)) 955 | | ) { 956 | | fl.log("WETH price from 800k to 900k was hit"); 957 | | } 958 | | if ( 959 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 960 | | price < WETH_MAX_PRICE * (10 ** _getPrecision(token)) 961 | | ) { 962 | | fl.log("WETH price from 900k to 1m was hit"); 963 | | } 964 | | } 965 | | function _logWBTCPriceBucket_Short_CancelDeposit( 966 | | uint256 price, 967 | | address token 968 | | ) internal { 969 | | if ( 970 | | price >= WBTC_MIN_PRICE && 971 | | price < 10_000e2 * (10 ** _getPrecision(token)) 972 | | ) { 973 | | fl.log("WBTC price from 1k to 10k was hit"); 974 | | } 975 | | if ( 976 | | price >= 10_000e2 * (10 ** _getPrecision(token)) && 977 | | price < 100_000e2 * (10 ** _getPrecision(token)) 978 | | ) { 979 | | fl.log("WBTC price from 10k to 100k was hit"); 980 | | } 981 | | if ( 982 | | price >= 100_000e2 * (10 ** _getPrecision(token)) && 983 | | price < 300_000e2 * (10 ** _getPrecision(token)) 984 | | ) { 985 | | fl.log("WBTC price from 100k to 300k was hit"); 986 | | } 987 | | if ( 988 | | price >= 300_000e2 * (10 ** _getPrecision(token)) && 989 | | price < 400_000e2 * (10 ** _getPrecision(token)) 990 | | ) { 991 | | fl.log("WBTC price from 300k to 400k was hit"); 992 | | } 993 | | if ( 994 | | price >= 400_000e2 * (10 ** _getPrecision(token)) && 995 | | price < 500_000e2 * (10 ** _getPrecision(token)) 996 | | ) { 997 | | fl.log("WBTC price from 400k to 500k was hit"); 998 | | } 999 | | if ( 1000 | | price >= 500_000e2 * (10 ** _getPrecision(token)) && 1001 | | price < 600_000e2 * (10 ** _getPrecision(token)) 1002 | | ) { 1003 | | fl.log("WBTC price from 500k to 600k was hit"); 1004 | | } 1005 | | if ( 1006 | | price >= 600_000e2 * (10 ** _getPrecision(token)) && 1007 | | price < 700_000e2 * (10 ** _getPrecision(token)) 1008 | | ) { 1009 | | fl.log("WBTC price from 600k to 700k was hit"); 1010 | | } 1011 | | if ( 1012 | | price >= 700_000e2 * (10 ** _getPrecision(token)) && 1013 | | price < 800_000e2 * (10 ** _getPrecision(token)) 1014 | | ) { 1015 | | fl.log("WBTC price from 700k to 800k was hit"); 1016 | | } 1017 | | if ( 1018 | | price >= 800_000e2 * (10 ** _getPrecision(token)) && 1019 | | price < 900_000e2 * (10 ** _getPrecision(token)) 1020 | | ) { 1021 | | fl.log("WBTC price from 800k to 900k was hit"); 1022 | | } 1023 | | if ( 1024 | | price >= 900_000e2 * (10 ** _getPrecision(token)) && 1025 | | price < WBTC_MAX_PRICE * (10 ** _getPrecision(token)) 1026 | | ) { 1027 | | fl.log("WBTC price from 900k to 1m was hit"); 1028 | | } 1029 | | } 1030 | | 1031 | | function _logSOLPriceBucket_Short_CancelDeposit( 1032 | | uint256 price, 1033 | | address token 1034 | | ) internal { 1035 | | if ( 1036 | | price >= SOL_MIN_PRICE && 1037 | | price < 100e4 * (10 ** _getPrecision(token)) 1038 | | ) { 1039 | | fl.log("SOL price from 1 to 100 was hit"); 1040 | | } 1041 | | if ( 1042 | | price >= 1000e4 * (10 ** _getPrecision(token)) && 1043 | | price < 10_000e4 * (10 ** _getPrecision(token)) 1044 | | ) { 1045 | | fl.log("SOL price from 1k to 10k was hit"); 1046 | | } 1047 | | if ( 1048 | | price >= 10_000e4 * (10 ** _getPrecision(token)) && 1049 | | price < 100_000e4 * (10 ** _getPrecision(token)) 1050 | | ) { 1051 | | fl.log("SOL price from 10k to 100k was hit"); 1052 | | } 1053 | | if ( 1054 | | price >= 100_000e4 * (10 ** _getPrecision(token)) && 1055 | | price < 200_000e4 * (10 ** _getPrecision(token)) 1056 | | ) { 1057 | | fl.log("SOL price from 100k to 200k was hit"); 1058 | | } 1059 | | if ( 1060 | | price >= 200_000e4 * (10 ** _getPrecision(token)) && 1061 | | price < 500_000e4 * (10 ** _getPrecision(token)) 1062 | | ) { 1063 | | fl.log("SOL price from 200k to 500k was hit"); 1064 | | } 1065 | | if ( 1066 | | price >= 500_000e4 * (10 ** _getPrecision(token)) && 1067 | | price < 600_000e4 * (10 ** _getPrecision(token)) 1068 | | ) { 1069 | | fl.log("SOL price from 500k to 600k was hit"); 1070 | | } 1071 | | if ( 1072 | | price >= 600_000e4 * (10 ** _getPrecision(token)) && 1073 | | price < 700_000e4 * (10 ** _getPrecision(token)) 1074 | | ) { 1075 | | fl.log("SOL price from 600k to 700k was hit"); 1076 | | } 1077 | | if ( 1078 | | price >= 700_000e4 * (10 ** _getPrecision(token)) && 1079 | | price < 800_000e4 * (10 ** _getPrecision(token)) 1080 | | ) { 1081 | | fl.log("SOL price from 700k to 800k was hit"); 1082 | | } 1083 | | if ( 1084 | | price >= 800_000e4 * (10 ** _getPrecision(token)) && 1085 | | price < 900_000e4 * (10 ** _getPrecision(token)) 1086 | | ) { 1087 | | fl.log("SOL price from 800k to 900k was hit"); 1088 | | } 1089 | | if ( 1090 | | price >= 900_000e4 * (10 ** _getPrecision(token)) && 1091 | | price < SOL_MAX_PRICE * (10 ** _getPrecision(token)) 1092 | | ) { 1093 | | fl.log("SOL price from 900k to 1m was hit"); 1094 | | } 1095 | | } 1096 | | 1097 | | // /\_/\ ___ 1098 | | // = o_o =_______ \ \ EXECUTE DEPOSIT COVERAGE 1099 | | // __^ __( \.__) ) 1100 | | // (@)<_____>__(_____)____/ 1101 | | 1102 | * | function _checkCoverageAfterDepositExecution( 1103 | | address market, 1104 | | uint userBalance, 1105 | | uint marketTotalSupply 1106 | | ) internal { 1107 | * | _logMarketTokenBySupplyCoverage_ExecuteDeposit( 1108 | * | market, 1109 | * | marketTotalSupply 1110 | | ); 1111 | * | _logMarketAmountByUser(userBalance); 1112 | | } 1113 | | 1114 | * | function _logMarketTokenBySupplyCoverage_ExecuteDeposit( 1115 | | address token, 1116 | | uint256 totalSupply 1117 | | ) internal { 1118 | * | if (token == address(market_0_WETH_USDC)) { 1119 | | if (totalSupply >= 0 && totalSupply < 1e6) { 1120 | | fl.log("TotalSupply bucket: 0 to 1e6"); 1121 | | } 1122 | | if (totalSupply >= 1e6 && totalSupply < 1e12) { 1123 | | fl.log("TotalSupply bucket: 1e6 to 1e12"); 1124 | | } 1125 | | if (totalSupply >= 1e12 && totalSupply < 1e18) { 1126 | | fl.log("TotalSupply bucket: 1e12 to 1e18"); 1127 | | } 1128 | | if (totalSupply >= 1e18 && totalSupply < 1e24) { 1129 | | fl.log("TotalSupply bucket: 1e18 to 1e24"); 1130 | | } 1131 | | if (totalSupply >= 1e24) { 1132 | | fl.log("TotalSupply bucket: 1e24 and above"); 1133 | | } 1134 | | } 1135 | | 1136 | * | if (token == address(market_WBTC_WBTC_USDC)) { 1137 | | if (totalSupply >= 0 && totalSupply < 1e6) { 1138 | | fl.log("TotalSupply bucket: 0 to 1e6"); 1139 | | } 1140 | | if (totalSupply >= 1e6 && totalSupply < 1e12) { 1141 | | fl.log("TotalSupply bucket: 1e6 to 1e12"); 1142 | | } 1143 | | if (totalSupply >= 1e12 && totalSupply < 1e18) { 1144 | | fl.log("TotalSupply bucket: 1e12 to 1e18"); 1145 | | } 1146 | | if (totalSupply >= 1e18 && totalSupply < 1e24) { 1147 | | fl.log("TotalSupply bucket: 1e18 to 1e24"); 1148 | | } 1149 | | if (totalSupply >= 1e24) { 1150 | | fl.log("TotalSupply bucket: 1e24 and above"); 1151 | | } 1152 | | } 1153 | * | if (token == address(market_WETH_WETH_USDC)) { 1154 | | if (totalSupply >= 0 && totalSupply < 1e6) { 1155 | | fl.log("TotalSupply bucket: 0 to 1e6"); 1156 | | } 1157 | | if (totalSupply >= 1e6 && totalSupply < 1e12) { 1158 | | fl.log("TotalSupply bucket: 1e6 to 1e12"); 1159 | | } 1160 | | if (totalSupply >= 1e12 && totalSupply < 1e18) { 1161 | | fl.log("TotalSupply bucket: 1e12 to 1e18"); 1162 | | } 1163 | | if (totalSupply >= 1e18 && totalSupply < 1e24) { 1164 | | fl.log("TotalSupply bucket: 1e18 to 1e24"); 1165 | | } 1166 | | if (totalSupply >= 1e24) { 1167 | | fl.log("TotalSupply bucket: 1e24 and above"); 1168 | | } 1169 | | } 1170 | * | if (token == address(market_WETH_WETH_USDT)) { 1171 | | if (totalSupply >= 0 && totalSupply < 1e6) { 1172 | | fl.log("TotalSupply bucket: 0 to 1e6"); 1173 | | } 1174 | | if (totalSupply >= 1e6 && totalSupply < 1e12) { 1175 | | fl.log("TotalSupply bucket: 1e6 to 1e12"); 1176 | | } 1177 | | if (totalSupply >= 1e12 && totalSupply < 1e18) { 1178 | | fl.log("TotalSupply bucket: 1e12 to 1e18"); 1179 | | } 1180 | | if (totalSupply >= 1e18 && totalSupply < 1e24) { 1181 | | fl.log("TotalSupply bucket: 1e18 to 1e24"); 1182 | | } 1183 | | if (totalSupply >= 1e24) { 1184 | | fl.log("TotalSupply bucket: 1e24 and above"); 1185 | | } 1186 | | } 1187 | | } 1188 | | 1189 | * | function _logMarketAmountByUser(uint256 amount) internal { 1190 | * | if (amount >= 0 && amount < 1e6) { 1191 | * | fl.log("Amount bucket: 0 to 1e6"); 1192 | | } 1193 | * | if (amount >= 1e6 && amount < 1e12) { 1194 | | fl.log("Amount bucket: 1e6 to 1e12"); 1195 | | } 1196 | * | if (amount >= 1e12 && amount < 1e18) { 1197 | | fl.log("Amount bucket: 1e12 to 1e18"); 1198 | | } 1199 | * | if (amount >= 1e18 && amount < 1e24) { 1200 | * | fl.log("Amount bucket: 1e18 to 1e24"); 1201 | | } 1202 | * | if (amount >= 1e24) { 1203 | * | fl.log("Amount bucket: 1e24 and above"); 1204 | | } 1205 | | } 1206 | | } 1207 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/LiquidationCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../properties/BeforeAfter.sol"; 6 | | 7 | | contract LiquidationCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ LIQUIDATION COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | * | function _checkPositionLiquitatableCoverage( 14 | | address account, 15 | | address market, 16 | | address collateralToken, 17 | | bool isLong, 18 | | PositionUtils.IsPositionLiquidatableInfo 19 | | memory isPositionLiquidatableInfo 20 | | ) internal { 21 | * | _logLiquidationAccountCoverage(account); 22 | * | _logLiquidationMarketCoverage(market); 23 | * | _logLiquidationCollateralTokenCoverage(collateralToken); 24 | * | _logLiquidationIsLongCoverage(isLong); 25 | * | _logRemainingCollateralUsdCoverage( 26 | * | isPositionLiquidatableInfo.remainingCollateralUsd 27 | | ); 28 | * | _logMinCollateralUsdCoverage( 29 | * | isPositionLiquidatableInfo.minCollateralUsd 30 | | ); 31 | * | _logMinCollateralUsdForLeverageCoverage( 32 | * | isPositionLiquidatableInfo.minCollateralUsdForLeverage 33 | | ); 34 | | } 35 | | 36 | * | function _logLiquidationIsLongCoverage(bool isLong) internal { 37 | * | if (isLong) { 38 | * | fl.log("Liquidation isLong is true"); 39 | | } else { 40 | | fl.log("Liquidation isLong is false"); 41 | | } 42 | | } 43 | | 44 | * | function _logLiquidationAccountCoverage(address account) internal { 45 | * | if (account == USER0) { 46 | | fl.log("Account USER0 hit"); 47 | | } 48 | * | if (account == USER1) { 49 | | fl.log("Account USER1 hit"); 50 | | } 51 | * | if (account == USER2) { 52 | | fl.log("Account USER2 hit"); 53 | | } 54 | * | if (account == USER3) { 55 | | fl.log("Account USER3 hit"); 56 | | } 57 | * | if (account == USER4) { 58 | | fl.log("Account USER4 hit"); 59 | | } 60 | * | if (account == USER5) { 61 | | fl.log("Account USER5 hit"); 62 | | } 63 | * | if (account == USER6) { 64 | | fl.log("Account USER6 hit"); 65 | | } 66 | * | if (account == USER7) { 67 | | fl.log("Account USER7 hit"); 68 | | } 69 | * | if (account == USER8) { 70 | | fl.log("Account USER8 hit"); 71 | | } 72 | * | if (account == USER9) { 73 | | fl.log("Account USER9 hit"); 74 | | } 75 | * | if (account == USER10) { 76 | | fl.log("Account USER10 hit"); 77 | | } 78 | * | if (account == USER11) { 79 | | fl.log("Account USER11 hit"); 80 | | } 81 | * | if (account == USER12) { 82 | | fl.log("Account USER12 hit"); 83 | | } 84 | * | if (account == USER13) { 85 | | fl.log("Account USER13 hit"); 86 | | } 87 | | } 88 | | 89 | * | function _logLiquidationMarketCoverage(address market) internal { 90 | * | if (market == address(market_0_WETH_USDC)) { 91 | | fl.log("Market market_0_WETH_USDC hit"); 92 | | } 93 | | 94 | * | if (market == address(market_WBTC_WBTC_USDC)) { 95 | * | fl.log("Market market_WBTC_WBTC_USDC hit"); 96 | | } 97 | * | if (market == address(market_WETH_WETH_USDC)) { 98 | * | fl.log("Market market_WETH_WETH_USDC hit"); 99 | | } 100 | * | if (market == address(market_WETH_WETH_USDT)) { 101 | | fl.log("Market market_WETH_WETH_USDT hit"); 102 | | } 103 | | } 104 | | 105 | * | function _logLiquidationCollateralTokenCoverage( 106 | | address collateralToken 107 | | ) internal { 108 | * | if (collateralToken == address(WETH)) { 109 | | fl.log("CollateralToken is WETH"); 110 | | } 111 | * | if (collateralToken == address(WBTC)) { 112 | | fl.log("CollateralToken is WBTC"); 113 | | } 114 | * | if (collateralToken == address(USDC)) { 115 | * | fl.log("CollateralToken is USDC"); 116 | | } 117 | * | if (collateralToken == address(USDT)) { 118 | | fl.log("CollateralToken is USDT"); 119 | | } 120 | * | if (collateralToken == address(SOL)) { 121 | | fl.log("CollateralToken is SOL"); 122 | | } 123 | | } 124 | * | function _logRemainingCollateralUsdCoverage( 125 | | int256 remainingCollateralUsd 126 | | ) internal { 127 | * | if (remainingCollateralUsd == 0) { 128 | | fl.log("RemainingCollateralUsd is 0"); 129 | | } 130 | * | if (remainingCollateralUsd > 0 && remainingCollateralUsd <= 1e6) { 131 | | fl.log("RemainingCollateralUsd is between 0 and 1e6"); 132 | | } 133 | * | if (remainingCollateralUsd > 1e6 && remainingCollateralUsd <= 1e12) { 134 | | fl.log("RemainingCollateralUsd is between 1e6 and 1e12"); 135 | | } 136 | * | if (remainingCollateralUsd > 1e12 && remainingCollateralUsd <= 1e18) { 137 | | fl.log("RemainingCollateralUsd is between 1e12 and 1e18"); 138 | | } 139 | * | if (remainingCollateralUsd > 1e18 && remainingCollateralUsd <= 1e24) { 140 | | fl.log("RemainingCollateralUsd is between 1e18 and 1e24"); 141 | | } 142 | * | if (remainingCollateralUsd > 1e24) { 143 | | fl.log("RemainingCollateralUsd is greater than 1e24"); 144 | | } 145 | * | if (remainingCollateralUsd < 0 && remainingCollateralUsd >= -1e6) { 146 | | fl.log("RemainingCollateralUsd is between 0 and -1e6"); 147 | | } 148 | * | if (remainingCollateralUsd < -1e6 && remainingCollateralUsd >= -1e12) { 149 | | fl.log("RemainingCollateralUsd is between -1e6 and -1e12"); 150 | | } 151 | * | if (remainingCollateralUsd < -1e12 && remainingCollateralUsd >= -1e18) { 152 | | fl.log("RemainingCollateralUsd is between -1e12 and -1e18"); 153 | | } 154 | * | if (remainingCollateralUsd < -1e18 && remainingCollateralUsd >= -1e24) { 155 | | fl.log("RemainingCollateralUsd is between -1e18 and -1e24"); 156 | | } 157 | * | if (remainingCollateralUsd < -1e24) { 158 | * | fl.log("RemainingCollateralUsd is less than -1e24"); 159 | | } 160 | | } 161 | | 162 | * | function _logMinCollateralUsdCoverage(int256 minCollateralUsd) internal { 163 | * | if (minCollateralUsd == 0) { 164 | | fl.log("MinCollateralUsd is 0"); 165 | | } 166 | * | if (minCollateralUsd > 0 && minCollateralUsd <= 1e6) { 167 | | fl.log("MinCollateralUsd is between 0 and 1e6"); 168 | | } 169 | * | if (minCollateralUsd > 1e6 && minCollateralUsd <= 1e12) { 170 | | fl.log("MinCollateralUsd is between 1e6 and 1e12"); 171 | | } 172 | * | if (minCollateralUsd > 1e12 && minCollateralUsd <= 1e18) { 173 | | fl.log("MinCollateralUsd is between 1e12 and 1e18"); 174 | | } 175 | * | if (minCollateralUsd > 1e18 && minCollateralUsd <= 1e24) { 176 | | fl.log("MinCollateralUsd is between 1e18 and 1e24"); 177 | | } 178 | * | if (minCollateralUsd > 1e24) { 179 | * | fl.log("MinCollateralUsd is greater than 1e24"); 180 | | } 181 | * | if (minCollateralUsd < 0 && minCollateralUsd >= -1e6) { 182 | | fl.log("MinCollateralUsd is between 0 and -1e6"); 183 | | } 184 | * | if (minCollateralUsd < -1e6 && minCollateralUsd >= -1e12) { 185 | | fl.log("MinCollateralUsd is between -1e6 and -1e12"); 186 | | } 187 | * | if (minCollateralUsd < -1e12 && minCollateralUsd >= -1e18) { 188 | | fl.log("MinCollateralUsd is between -1e12 and -1e18"); 189 | | } 190 | * | if (minCollateralUsd < -1e18 && minCollateralUsd >= -1e24) { 191 | | fl.log("MinCollateralUsd is between -1e18 and -1e24"); 192 | | } 193 | * | if (minCollateralUsd < -1e24) { 194 | | fl.log("MinCollateralUsd is less than -1e24"); 195 | | } 196 | | } 197 | | 198 | * | function _logMinCollateralUsdForLeverageCoverage( 199 | | int256 minCollateralUsdForLeverage 200 | | ) internal { 201 | * | if (minCollateralUsdForLeverage == 0) { 202 | | fl.log("MinCollateralUsdForLeverage is 0"); 203 | | } 204 | * | if ( 205 | * | minCollateralUsdForLeverage > 0 && 206 | * | minCollateralUsdForLeverage <= 1e6 207 | | ) { 208 | | fl.log("MinCollateralUsdForLeverage is between 0 and 1e6"); 209 | | } 210 | * | if ( 211 | * | minCollateralUsdForLeverage > 1e6 && 212 | * | minCollateralUsdForLeverage <= 1e12 213 | | ) { 214 | | fl.log("MinCollateralUsdForLeverage is between 1e6 and 1e12"); 215 | | } 216 | * | if ( 217 | * | minCollateralUsdForLeverage > 1e12 && 218 | * | minCollateralUsdForLeverage <= 1e18 219 | | ) { 220 | | fl.log("MinCollateralUsdForLeverage is between 1e12 and 1e18"); 221 | | } 222 | * | if ( 223 | * | minCollateralUsdForLeverage > 1e18 && 224 | * | minCollateralUsdForLeverage <= 1e24 225 | | ) { 226 | | fl.log("MinCollateralUsdForLeverage is between 1e18 and 1e24"); 227 | | } 228 | * | if (minCollateralUsdForLeverage > 1e24) { 229 | * | fl.log("MinCollateralUsdForLeverage is greater than 1e24"); 230 | | } 231 | * | if ( 232 | * | minCollateralUsdForLeverage < 0 && 233 | | minCollateralUsdForLeverage >= -1e6 234 | | ) { 235 | | fl.log("MinCollateralUsdForLeverage is between 0 and -1e6"); 236 | | } 237 | * | if ( 238 | * | minCollateralUsdForLeverage < -1e6 && 239 | | minCollateralUsdForLeverage >= -1e12 240 | | ) { 241 | | fl.log("MinCollateralUsdForLeverage is between -1e6 and -1e12"); 242 | | } 243 | * | if ( 244 | * | minCollateralUsdForLeverage < -1e12 && 245 | | minCollateralUsdForLeverage >= -1e18 246 | | ) { 247 | | fl.log("MinCollateralUsdForLeverage is between -1e12 and -1e18"); 248 | | } 249 | * | if ( 250 | * | minCollateralUsdForLeverage < -1e18 && 251 | | minCollateralUsdForLeverage >= -1e24 252 | | ) { 253 | | fl.log("MinCollateralUsdForLeverage is between -1e18 and -1e24"); 254 | | } 255 | * | if (minCollateralUsdForLeverage < -1e24) { 256 | | fl.log("MinCollateralUsdForLeverage is less than -1e24"); 257 | | } 258 | | } 259 | | } 260 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/PositionCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./positionCoverage/CreateOrderCoverage.sol"; 6 | | import "./positionCoverage/CancelOrderCoverage.sol"; 7 | | import "./positionCoverage/IncreasePositionInfoCoverage.sol"; 8 | | import "./positionCoverage/IncreasePositionMarketCoverage.sol"; 9 | | import "./positionCoverage/DecreasePositionInfoCoverage.sol"; 10 | | import "./positionCoverage/DecreasePositionMarketCoverage.sol"; 11 | | 12 | | contract PositionCoverage is 13 | | CreateOrderCoverage, 14 | | CancelOrderCoverage, 15 | | IncreasePositionInfoCoverage, 16 | | IncreasePositionMarketCoverage, 17 | | DecreasePositionInfoCoverage, 18 | | DecreasePositionMarketCoverage 19 | | {} 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/ShiftCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./shiftCoverage/ShiftCreatedCoverage.sol"; 6 | | import "./shiftCoverage/ShiftCancelCoverage.sol"; 7 | | import "./shiftCoverage/ShiftExecutedCoverage.sol"; 8 | | 9 | | contract ShiftCoverage is ShiftCreatedCoverage, ShiftCancelCoverage, ShiftExecutedCoverage {} 10 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/WithdrawalCoverage.sol 1 | | pragma solidity ^0.8.0; 2 | | 3 | | import "./withdrawalCoverage/WithdrawalCreatedCoverage.sol"; 4 | | import "./withdrawalCoverage/WithdrawalCancelCoverage.sol"; 5 | | import "./withdrawalCoverage/WithdrawalExecuteCoverage.sol"; 6 | | import "./withdrawalCoverage/WithdrawalExecuteAtomicCoverage.sol"; 7 | | 8 | | contract WithdrawalCoverage is 9 | | WithdrawalCreatedCoverage, 10 | | WithdrawalCancelCoverage, 11 | | WithdrawalExecuteCoverage, 12 | | WithdrawalExecuteAtomicCoverage 13 | | {} 14 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/CancelOrderCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract CancelOrderCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ CANCEL ORDER COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | | function _checkOrderCancelCoverage( 14 | | OrderCreated memory orderToCancel 15 | | ) internal { 16 | | _logReceiverCoverage_cancelOrder( 17 | | orderToCancel.createOrderParams.addresses.receiver 18 | | ); 19 | | _logCancellationReceiverCoverage_cancelOrder( 20 | | orderToCancel.createOrderParams.addresses.cancellationReceiver 21 | | ); 22 | | _logCallbackContractCoverage_cancelOrder( 23 | | orderToCancel.createOrderParams.addresses.callbackContract 24 | | ); 25 | | _logUiFeeReceiverCoverage_cancelOrder( 26 | | orderToCancel.createOrderParams.addresses.uiFeeReceiver 27 | | ); 28 | | _logInitialCollateralTokenCoverage_cancelOrder( 29 | | orderToCancel.createOrderParams.addresses.initialCollateralToken 30 | | ); 31 | | _logMarketCoverage_cancelOrder( 32 | | orderToCancel.createOrderParams.addresses.market 33 | | ); 34 | | _logSwapPathCoverage_cancelOrder( 35 | | orderToCancel.createOrderParams.addresses.swapPath 36 | | ); 37 | | _logOrderTypeCoverage_cancelOrder( 38 | | orderToCancel.createOrderParams.orderType 39 | | ); 40 | | _logDecreasePositionSwapTypeCoverage_cancelOrder( 41 | | orderToCancel.createOrderParams.decreasePositionSwapType 42 | | ); 43 | | _logIsLongCoverage_cancelOrder(orderToCancel.createOrderParams.isLong); 44 | | _logShouldUnwrapNativeTokenCoverage_cancelOrder( 45 | | orderToCancel.createOrderParams.shouldUnwrapNativeToken 46 | | ); 47 | | _logAutoCancelCoverage_cancelOrder( 48 | | orderToCancel.createOrderParams.autoCancel 49 | | ); 50 | | _logReferralCodeCoverage_cancelOrder( 51 | | orderToCancel.createOrderParams.referralCode 52 | | ); 53 | | _logSizeDeltaUsdCoverage_cancelOrder( 54 | | orderToCancel.createOrderParams.numbers.sizeDeltaUsd 55 | | ); 56 | | _logInitialCollateralDeltaAmountCoverage_cancelOrder( 57 | | orderToCancel.createOrderParams.numbers.initialCollateralDeltaAmount 58 | | ); 59 | | _logTriggerPriceCoverage_cancelOrder( 60 | | orderToCancel.createOrderParams.numbers.triggerPrice 61 | | ); 62 | | _logAcceptablePriceCoverage_cancelOrder( 63 | | orderToCancel.createOrderParams.numbers.acceptablePrice 64 | | ); 65 | | _logExecutionFeeCoverage_cancelOrder( 66 | | orderToCancel.createOrderParams.numbers.executionFee 67 | | ); 68 | | _logCallbackGasLimitCoverage_cancelOrder( 69 | | orderToCancel.createOrderParams.numbers.callbackGasLimit 70 | | ); 71 | | _logMinOutputAmountCoverage_cancelOrder( 72 | | orderToCancel.createOrderParams.numbers.minOutputAmount 73 | | ); 74 | | _logKeyCoverage_cancelOrder(orderToCancel.key); 75 | | _logUpdatedAtCoverage_cancelOrder(orderToCancel.updatedAt); 76 | | _logUserCoverage_cancelOrder(orderToCancel.user); 77 | | _logHandlerTypeCoverage_cancelOrder(orderToCancel.handlerType); 78 | | _logAmountSentCoverage_cancelOrder(orderToCancel.amountSent); 79 | | _logIsCloseCoverage_cancelOrder(orderToCancel.isClose); 80 | | } 81 | | 82 | | function _logReceiverCoverage_cancelOrder(address receiver) internal { 83 | | if (receiver == USER0) { 84 | | fl.log("Receiver USER0 hit"); 85 | | } 86 | | if (receiver == USER1) { 87 | | fl.log("Receiver USER1 hit"); 88 | | } 89 | | if (receiver == USER2) { 90 | | fl.log("Receiver USER2 hit"); 91 | | } 92 | | if (receiver == USER3) { 93 | | fl.log("Receiver USER3 hit"); 94 | | } 95 | | if (receiver == USER4) { 96 | | fl.log("Receiver USER4 hit"); 97 | | } 98 | | if (receiver == USER5) { 99 | | fl.log("Receiver USER5 hit"); 100 | | } 101 | | if (receiver == USER6) { 102 | | fl.log("Receiver USER6 hit"); 103 | | } 104 | | if (receiver == USER7) { 105 | | fl.log("Receiver USER7 hit"); 106 | | } 107 | | if (receiver == USER8) { 108 | | fl.log("Receiver USER8 hit"); 109 | | } 110 | | if (receiver == USER9) { 111 | | fl.log("Receiver USER9 hit"); 112 | | } 113 | | if (receiver == USER10) { 114 | | fl.log("Receiver USER10 hit"); 115 | | } 116 | | if (receiver == USER11) { 117 | | fl.log("Receiver USER11 hit"); 118 | | } 119 | | if (receiver == USER12) { 120 | | fl.log("Receiver USER12 hit"); 121 | | } 122 | | if (receiver == USER13) { 123 | | fl.log("Receiver USER13 hit"); 124 | | } 125 | | } 126 | | 127 | | function _logCancellationReceiverCoverage_cancelOrder( 128 | | address cancellationReceiver 129 | | ) internal { 130 | | if (cancellationReceiver == USER0) { 131 | | fl.log("CancellationReceiver USER0 hit"); 132 | | } 133 | | if (cancellationReceiver == USER1) { 134 | | fl.log("CancellationReceiver USER1 hit"); 135 | | } 136 | | if (cancellationReceiver == USER2) { 137 | | fl.log("CancellationReceiver USER2 hit"); 138 | | } 139 | | if (cancellationReceiver == USER3) { 140 | | fl.log("CancellationReceiver USER3 hit"); 141 | | } 142 | | if (cancellationReceiver == USER4) { 143 | | fl.log("CancellationReceiver USER4 hit"); 144 | | } 145 | | if (cancellationReceiver == USER5) { 146 | | fl.log("CancellationReceiver USER5 hit"); 147 | | } 148 | | if (cancellationReceiver == USER6) { 149 | | fl.log("CancellationReceiver USER6 hit"); 150 | | } 151 | | if (cancellationReceiver == USER7) { 152 | | fl.log("CancellationReceiver USER7 hit"); 153 | | } 154 | | if (cancellationReceiver == USER8) { 155 | | fl.log("CancellationReceiver USER8 hit"); 156 | | } 157 | | if (cancellationReceiver == USER9) { 158 | | fl.log("CancellationReceiver USER9 hit"); 159 | | } 160 | | if (cancellationReceiver == USER10) { 161 | | fl.log("CancellationReceiver USER10 hit"); 162 | | } 163 | | if (cancellationReceiver == USER11) { 164 | | fl.log("CancellationReceiver USER11 hit"); 165 | | } 166 | | if (cancellationReceiver == USER12) { 167 | | fl.log("CancellationReceiver USER12 hit"); 168 | | } 169 | | if (cancellationReceiver == USER13) { 170 | | fl.log("CancellationReceiver USER13 hit"); 171 | | } 172 | | } 173 | | 174 | | function _logCallbackContractCoverage_cancelOrder( 175 | | address callbackContract 176 | | ) internal { 177 | | if (callbackContract == address(0)) { 178 | | fl.log("CallbackContract is address(0)"); 179 | | } else { 180 | | fl.log("CallbackContract is non-zero address"); 181 | | } 182 | | } 183 | | 184 | | function _logUiFeeReceiverCoverage_cancelOrder( 185 | | address uiFeeReceiver 186 | | ) internal { 187 | | if (uiFeeReceiver == address(0)) { 188 | | fl.log("UiFeeReceiver is address(0)"); 189 | | } else { 190 | | fl.log("UiFeeReceiver is non-zero address"); 191 | | } 192 | | } 193 | | 194 | | function _logInitialCollateralTokenCoverage_cancelOrder( 195 | | address initialCollateralToken 196 | | ) internal { 197 | | if (initialCollateralToken == address(WETH)) { 198 | | fl.log("InitialCollateralToken is WETH"); 199 | | } 200 | | if (initialCollateralToken == address(WBTC)) { 201 | | fl.log("InitialCollateralToken is WBTC"); 202 | | } 203 | | if (initialCollateralToken == address(USDC)) { 204 | | fl.log("InitialCollateralToken is USDC"); 205 | | } 206 | | if (initialCollateralToken == address(USDT)) { 207 | | fl.log("InitialCollateralToken is USDT"); 208 | | } 209 | | if (initialCollateralToken == address(SOL)) { 210 | | fl.log("InitialCollateralToken is SOL"); 211 | | } 212 | | } 213 | | 214 | | function _logMarketCoverage_cancelOrder(address market) internal { 215 | | if (market == address(market_0_WETH_USDC)) { 216 | | fl.log("Market market_0_WETH_USDC hit"); 217 | | } 218 | | 219 | | if (market == address(market_WBTC_WBTC_USDC)) { 220 | | fl.log("Market market_WBTC_WBTC_USDC hit"); 221 | | } 222 | | if (market == address(market_WETH_WETH_USDC)) { 223 | | fl.log("Market market_WETH_WETH_USDC hit"); 224 | | } 225 | | if (market == address(market_WETH_WETH_USDT)) { 226 | | fl.log("Market market_WETH_WETH_USDT hit"); 227 | | } 228 | | } 229 | | 230 | | function _logSwapPathCoverage_cancelOrder( 231 | | address[] memory swapPath 232 | | ) internal { 233 | | if (swapPath.length == 0) { 234 | | fl.log("SwapPath is empty"); 235 | | } 236 | | if (swapPath.length == 1) { 237 | | fl.log("SwapPath has 1 element"); 238 | | } 239 | | if (swapPath.length == 2) { 240 | | fl.log("SwapPath has 2 elements"); 241 | | } 242 | | if (swapPath.length >= 3) { 243 | | fl.log("SwapPath has 3 or more elements"); 244 | | } 245 | | } 246 | | 247 | | function _logOrderTypeCoverage_cancelOrder( 248 | | Order.OrderType orderType 249 | | ) internal { 250 | | if (orderType == Order.OrderType.MarketSwap) { 251 | | fl.log("OrderType is MarketSwap"); 252 | | } 253 | | if (orderType == Order.OrderType.LimitSwap) { 254 | | fl.log("OrderType is LimitSwap"); 255 | | } 256 | | if (orderType == Order.OrderType.MarketIncrease) { 257 | | fl.log("OrderType is MarketIncrease"); 258 | | } 259 | | if (orderType == Order.OrderType.LimitIncrease) { 260 | | fl.log("OrderType is LimitIncrease"); 261 | | } 262 | | if (orderType == Order.OrderType.MarketDecrease) { 263 | | fl.log("OrderType is MarketDecrease"); 264 | | } 265 | | if (orderType == Order.OrderType.LimitDecrease) { 266 | | fl.log("OrderType is LimitDecrease"); 267 | | } 268 | | if (orderType == Order.OrderType.StopLossDecrease) { 269 | | fl.log("OrderType is StopLossDecrease"); 270 | | } 271 | | if (orderType == Order.OrderType.Liquidation) { 272 | | fl.log("OrderType is Liquidation"); 273 | | } 274 | | } 275 | | 276 | | function _logDecreasePositionSwapTypeCoverage_cancelOrder( 277 | | Order.DecreasePositionSwapType decreasePositionSwapType 278 | | ) internal { 279 | | if (decreasePositionSwapType == Order.DecreasePositionSwapType.NoSwap) { 280 | | fl.log("DecreasePositionSwapType is NoSwap"); 281 | | } 282 | | if ( 283 | | decreasePositionSwapType == 284 | | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken 285 | | ) { 286 | | fl.log("DecreasePositionSwapType is SwapPnlTokenToCollateralToken"); 287 | | } 288 | | if ( 289 | | decreasePositionSwapType == 290 | | Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken 291 | | ) { 292 | | fl.log("DecreasePositionSwapType is SwapCollateralTokenToPnlToken"); 293 | | } 294 | | } 295 | | 296 | | function _logIsLongCoverage_cancelOrder(bool isLong) internal { 297 | | if (isLong) { 298 | | fl.log("IsLong is true"); 299 | | } else { 300 | | fl.log("IsLong is false"); 301 | | } 302 | | } 303 | | 304 | | function _logShouldUnwrapNativeTokenCoverage_cancelOrder( 305 | | bool shouldUnwrapNativeToken 306 | | ) internal { 307 | | if (shouldUnwrapNativeToken) { 308 | | fl.log("ShouldUnwrapNativeToken is true"); 309 | | } else { 310 | | fl.log("ShouldUnwrapNativeToken is false"); 311 | | } 312 | | } 313 | | 314 | | function _logAutoCancelCoverage_cancelOrder(bool autoCancel) internal { 315 | | if (autoCancel) { 316 | | fl.log("AutoCancel is true"); 317 | | } else { 318 | | fl.log("AutoCancel is false"); 319 | | } 320 | | } 321 | | 322 | | function _logReferralCodeCoverage_cancelOrder( 323 | | bytes32 referralCode 324 | | ) internal { 325 | | if (referralCode == bytes32(0)) { 326 | | fl.log("ReferralCode is empty"); 327 | | } else { 328 | | fl.log("ReferralCode is non-empty"); 329 | | } 330 | | } 331 | | 332 | | function _logSizeDeltaUsdCoverage_cancelOrder( 333 | | uint256 sizeDeltaUsd 334 | | ) internal { 335 | | if (sizeDeltaUsd == 0) { 336 | | fl.log("SizeDeltaUsd is 0"); 337 | | } 338 | | if (sizeDeltaUsd > 0 && sizeDeltaUsd <= 1e6) { 339 | | fl.log("SizeDeltaUsd is between 0 and 1e6"); 340 | | } 341 | | if (sizeDeltaUsd > 1e6 && sizeDeltaUsd <= 1e12) { 342 | | fl.log("SizeDeltaUsd is between 1e6 and 1e12"); 343 | | } 344 | | if (sizeDeltaUsd > 1e12 && sizeDeltaUsd <= 1e18) { 345 | | fl.log("SizeDeltaUsd is between 1e12 and 1e18"); 346 | | } 347 | | if (sizeDeltaUsd > 1e18 && sizeDeltaUsd <= 1e24) { 348 | | fl.log("SizeDeltaUsd is between 1e18 and 1e24"); 349 | | } 350 | | if (sizeDeltaUsd > 1e24) { 351 | | fl.log("SizeDeltaUsd is greater than 1e24"); 352 | | } 353 | | } 354 | | 355 | | function _logInitialCollateralDeltaAmountCoverage_cancelOrder( 356 | | uint256 initialCollateralDeltaAmount 357 | | ) internal { 358 | | if (initialCollateralDeltaAmount == 0) { 359 | | fl.log("InitialCollateralDeltaAmount is 0"); 360 | | } 361 | | if ( 362 | | initialCollateralDeltaAmount > 0 && 363 | | initialCollateralDeltaAmount <= 1e6 364 | | ) { 365 | | fl.log("InitialCollateralDeltaAmount is between 0 and 1e6"); 366 | | } 367 | | if ( 368 | | initialCollateralDeltaAmount > 1e6 && 369 | | initialCollateralDeltaAmount <= 1e12 370 | | ) { 371 | | fl.log("InitialCollateralDeltaAmount is between 1e6 and 1e12"); 372 | | } 373 | | if ( 374 | | initialCollateralDeltaAmount > 1e12 && 375 | | initialCollateralDeltaAmount <= 1e18 376 | | ) { 377 | | fl.log("InitialCollateralDeltaAmount is between 1e12 and 1e18"); 378 | | } 379 | | if ( 380 | | initialCollateralDeltaAmount > 1e18 && 381 | | initialCollateralDeltaAmount <= 1e24 382 | | ) { 383 | | fl.log("InitialCollateralDeltaAmount is between 1e18 and 1e24"); 384 | | } 385 | | if (initialCollateralDeltaAmount > 1e24) { 386 | | fl.log("InitialCollateralDeltaAmount is greater than 1e24"); 387 | | } 388 | | } 389 | | 390 | | function _logTriggerPriceCoverage_cancelOrder( 391 | | uint256 triggerPrice 392 | | ) internal { 393 | | if (triggerPrice == 0) { 394 | | fl.log("TriggerPrice is 0"); 395 | | } 396 | | if (triggerPrice > 0 && triggerPrice <= 1e6) { 397 | | fl.log("TriggerPrice is between 0 and 1e6"); 398 | | } 399 | | if (triggerPrice > 1e6 && triggerPrice <= 1e12) { 400 | | fl.log("TriggerPrice is between 1e6 and 1e12"); 401 | | } 402 | | if (triggerPrice > 1e12 && triggerPrice <= 1e18) { 403 | | fl.log("TriggerPrice is between 1e12 and 1e18"); 404 | | } 405 | | if (triggerPrice > 1e18 && triggerPrice <= 1e24) { 406 | | fl.log("TriggerPrice is between 1e18 and 1e24"); 407 | | } 408 | | if (triggerPrice > 1e24) { 409 | | fl.log("TriggerPrice is greater than 1e24"); 410 | | } 411 | | } 412 | | 413 | | function _logAcceptablePriceCoverage_cancelOrder( 414 | | uint256 acceptablePrice 415 | | ) internal { 416 | | if (acceptablePrice == 0) { 417 | | fl.log("AcceptablePrice is 0"); 418 | | } 419 | | if (acceptablePrice > 0 && acceptablePrice <= 1e6) { 420 | | fl.log("AcceptablePrice is between 0 and 1e6"); 421 | | } 422 | | if (acceptablePrice > 1e6 && acceptablePrice <= 1e12) { 423 | | fl.log("AcceptablePrice is between 1e6 and 1e12"); 424 | | } 425 | | if (acceptablePrice > 1e12 && acceptablePrice <= 1e18) { 426 | | fl.log("AcceptablePrice is between 1e12 and 1e18"); 427 | | } 428 | | if (acceptablePrice > 1e18 && acceptablePrice <= 1e24) { 429 | | fl.log("AcceptablePrice is between 1e18 and 1e24"); 430 | | } 431 | | if (acceptablePrice > 1e24) { 432 | | fl.log("AcceptablePrice is greater than 1e24"); 433 | | } 434 | | } 435 | | 436 | | function _logExecutionFeeCoverage_cancelOrder( 437 | | uint256 executionFee 438 | | ) internal { 439 | | if (executionFee == 0) { 440 | | fl.log("ExecutionFee is 0"); 441 | | } 442 | | if (executionFee > 0 && executionFee <= 1e6) { 443 | | fl.log("ExecutionFee is between 0 and 1e6"); 444 | | } 445 | | if (executionFee > 1e6 && executionFee <= 1e12) { 446 | | fl.log("ExecutionFee is between 1e6 and 1e12"); 447 | | } 448 | | if (executionFee > 1e12 && executionFee <= 1e18) { 449 | | fl.log("ExecutionFee is between 1e12 and 1e18"); 450 | | } 451 | | if (executionFee > 1e18 && executionFee <= 1e24) { 452 | | fl.log("ExecutionFee is between 1e18 and 1e24"); 453 | | } 454 | | if (executionFee > 1e24) { 455 | | fl.log("ExecutionFee is greater than 1e24"); 456 | | } 457 | | } 458 | | 459 | | function _logCallbackGasLimitCoverage_cancelOrder( 460 | | uint256 callbackGasLimit 461 | | ) internal { 462 | | if (callbackGasLimit == 0) { 463 | | fl.log("CallbackGasLimit is 0"); 464 | | } 465 | | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 466 | | fl.log("CallbackGasLimit is between 0 and 1e6"); 467 | | } 468 | | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 469 | | fl.log("CallbackGasLimit is between 1e6 and 1e12"); 470 | | } 471 | | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 472 | | fl.log("CallbackGasLimit is between 1e12 and 1e18"); 473 | | } 474 | | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 475 | | fl.log("CallbackGasLimit is between 1e18 and 1e24"); 476 | | } 477 | | if (callbackGasLimit > 1e24) { 478 | | fl.log("CallbackGasLimit is greater than 1e24"); 479 | | } 480 | | } 481 | | 482 | | function _logMinOutputAmountCoverage_cancelOrder( 483 | | uint256 minOutputAmount 484 | | ) internal { 485 | | if (minOutputAmount == 0) { 486 | | fl.log("MinOutputAmount is 0"); 487 | | } 488 | | if (minOutputAmount > 0 && minOutputAmount <= 1e6) { 489 | | fl.log("MinOutputAmount is between 0 and 1e6"); 490 | | } 491 | | if (minOutputAmount > 1e6 && minOutputAmount <= 1e12) { 492 | | fl.log("MinOutputAmount is between 1e6 and 1e12"); 493 | | } 494 | | if (minOutputAmount > 1e12 && minOutputAmount <= 1e18) { 495 | | fl.log("MinOutputAmount is between 1e12 and 1e18"); 496 | | } 497 | | if (minOutputAmount > 1e18 && minOutputAmount <= 1e24) { 498 | | fl.log("MinOutputAmount is between 1e18 and 1e24"); 499 | | } 500 | | if (minOutputAmount > 1e24) { 501 | | fl.log("MinOutputAmount is greater than 1e24"); 502 | | } 503 | | } 504 | | 505 | | function _logKeyCoverage_cancelOrder(bytes32 key) internal { 506 | | if (key == bytes32(0)) { 507 | | fl.log("Key is empty"); 508 | | } else { 509 | | fl.log("Key is non-empty"); 510 | | } 511 | | } 512 | | 513 | | function _logUpdatedAtCoverage_cancelOrder(uint256 updatedAt) internal { 514 | | if (updatedAt == 0) { 515 | | fl.log("UpdatedAt is 0"); 516 | | } else { 517 | | fl.log("UpdatedAt is non-zero"); 518 | | } 519 | | } 520 | | 521 | | function _logUserCoverage_cancelOrder(address user) internal { 522 | | if (user == USER0) { 523 | | fl.log("User USER0 hit"); 524 | | } 525 | | if (user == USER1) { 526 | | fl.log("User USER1 hit"); 527 | | } 528 | | if (user == USER2) { 529 | | fl.log("User USER2 hit"); 530 | | } 531 | | if (user == USER3) { 532 | | fl.log("User USER3 hit"); 533 | | } 534 | | if (user == USER4) { 535 | | fl.log("User USER4 hit"); 536 | | } 537 | | if (user == USER5) { 538 | | fl.log("User USER5 hit"); 539 | | } 540 | | if (user == USER6) { 541 | | fl.log("User USER6 hit"); 542 | | } 543 | | if (user == USER7) { 544 | | fl.log("User USER7 hit"); 545 | | } 546 | | if (user == USER8) { 547 | | fl.log("User USER8 hit"); 548 | | } 549 | | if (user == USER9) { 550 | | fl.log("User USER9 hit"); 551 | | } 552 | | if (user == USER10) { 553 | | fl.log("User USER10 hit"); 554 | | } 555 | | if (user == USER11) { 556 | | fl.log("User USER11 hit"); 557 | | } 558 | | if (user == USER12) { 559 | | fl.log("User USER12 hit"); 560 | | } 561 | | if (user == USER13) { 562 | | fl.log("User USER13 hit"); 563 | | } 564 | | } 565 | | 566 | | function _logHandlerTypeCoverage_cancelOrder(bytes32 handlerType) internal { 567 | | if (handlerType == bytes32(0)) { 568 | | fl.log("HandlerType is empty"); 569 | | } else { 570 | | fl.log("HandlerType is non-empty"); 571 | | } 572 | | } 573 | | 574 | | function _logAmountSentCoverage_cancelOrder(uint256 amountSent) internal { 575 | | if (amountSent == 0) { 576 | | fl.log("AmountSent is 0"); 577 | | } 578 | | if (amountSent > 0 && amountSent <= 1e6) { 579 | | fl.log("AmountSent is between 0 and 1e6"); 580 | | } 581 | | if (amountSent > 1e6 && amountSent <= 1e12) { 582 | | fl.log("AmountSent is between 1e6 and 1e12"); 583 | | } 584 | | if (amountSent > 1e12 && amountSent <= 1e18) { 585 | | fl.log("AmountSent is between 1e12 and 1e18"); 586 | | } 587 | | if (amountSent > 1e18 && amountSent <= 1e24) { 588 | | fl.log("AmountSent is between 1e18 and 1e24"); 589 | | } 590 | | if (amountSent > 1e24) { 591 | | fl.log("AmountSent is greater than 1e24"); 592 | | } 593 | | } 594 | | 595 | | function _logIsCloseCoverage_cancelOrder(bool isClose) internal { 596 | | if (isClose) { 597 | | fl.log("IsClose is true"); 598 | | } else { 599 | | fl.log("IsClose is false"); 600 | | } 601 | | } 602 | | } 603 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/CreateOrderCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract CreateOrderCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ CREATE ORDER COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | * | function _checkOrderCreatedCoverage( 14 | | OrderCreated memory orderCreated 15 | | ) internal { 16 | * | _logReceiverCoverage(orderCreated.createOrderParams.addresses.receiver); 17 | * | _logCancellationReceiverCoverage( 18 | * | orderCreated.createOrderParams.addresses.cancellationReceiver 19 | | ); 20 | * | _logCallbackContractCoverage( 21 | * | orderCreated.createOrderParams.addresses.callbackContract 22 | | ); 23 | * | _logUiFeeReceiverCoverage( 24 | * | orderCreated.createOrderParams.addresses.uiFeeReceiver 25 | | ); 26 | * | _logInitialCollateralTokenCoverage( 27 | * | orderCreated.createOrderParams.addresses.initialCollateralToken 28 | | ); 29 | * | _logMarketCoverage(orderCreated.createOrderParams.addresses.market); 30 | * | _logSwapPathCoverage(orderCreated.createOrderParams.addresses.swapPath); 31 | * | _logOrderTypeCoverage(orderCreated.createOrderParams.orderType); 32 | * | _logDecreasePositionSwapTypeCoverage( 33 | * | orderCreated.createOrderParams.decreasePositionSwapType 34 | | ); 35 | * | _logIsLongCoverage(orderCreated.createOrderParams.isLong); 36 | * | _logShouldUnwrapNativeTokenCoverage( 37 | * | orderCreated.createOrderParams.shouldUnwrapNativeToken 38 | | ); 39 | * | _logAutoCancelCoverage(orderCreated.createOrderParams.autoCancel); 40 | * | _logReferralCodeCoverage(orderCreated.createOrderParams.referralCode); 41 | * | _logSizeDeltaUsdCoverage( 42 | * | orderCreated.createOrderParams.numbers.sizeDeltaUsd 43 | | ); 44 | * | _logInitialCollateralDeltaAmountCoverage( 45 | * | orderCreated.createOrderParams.numbers.initialCollateralDeltaAmount 46 | | ); 47 | * | _logTriggerPriceCoverage( 48 | * | orderCreated.createOrderParams.numbers.triggerPrice 49 | | ); 50 | * | _logAcceptablePriceCoverage( 51 | * | orderCreated.createOrderParams.numbers.acceptablePrice 52 | | ); 53 | * | _logExecutionFeeCoverage( 54 | * | orderCreated.createOrderParams.numbers.executionFee 55 | | ); 56 | * | _logCallbackGasLimitCoverage( 57 | * | orderCreated.createOrderParams.numbers.callbackGasLimit 58 | | ); 59 | * | _logMinOutputAmountCoverage( 60 | * | orderCreated.createOrderParams.numbers.minOutputAmount 61 | | ); 62 | * | _logKeyCoverage(orderCreated.key); 63 | * | _logUpdatedAtCoverage(orderCreated.updatedAt); 64 | * | _logUserCoverage(orderCreated.user); 65 | * | _logHandlerTypeCoverage(orderCreated.handlerType); 66 | * | _logAmountSentCoverage(orderCreated.amountSent); 67 | * | _logIsCloseCoverage(orderCreated.isClose); 68 | | } 69 | | 70 | * | function _logReceiverCoverage(address receiver) internal { 71 | * | if (receiver == USER0) { 72 | * | fl.log("Receiver USER0 hit"); 73 | | } 74 | * | if (receiver == USER1) { 75 | * | fl.log("Receiver USER1 hit"); 76 | | } 77 | * | if (receiver == USER2) { 78 | * | fl.log("Receiver USER2 hit"); 79 | | } 80 | * | if (receiver == USER3) { 81 | * | fl.log("Receiver USER3 hit"); 82 | | } 83 | * | if (receiver == USER4) { 84 | * | fl.log("Receiver USER4 hit"); 85 | | } 86 | * | if (receiver == USER5) { 87 | * | fl.log("Receiver USER5 hit"); 88 | | } 89 | * | if (receiver == USER6) { 90 | * | fl.log("Receiver USER6 hit"); 91 | | } 92 | * | if (receiver == USER7) { 93 | * | fl.log("Receiver USER7 hit"); 94 | | } 95 | * | if (receiver == USER8) { 96 | * | fl.log("Receiver USER8 hit"); 97 | | } 98 | * | if (receiver == USER9) { 99 | * | fl.log("Receiver USER9 hit"); 100 | | } 101 | * | if (receiver == USER10) { 102 | * | fl.log("Receiver USER10 hit"); 103 | | } 104 | * | if (receiver == USER11) { 105 | * | fl.log("Receiver USER11 hit"); 106 | | } 107 | * | if (receiver == USER12) { 108 | * | fl.log("Receiver USER12 hit"); 109 | | } 110 | * | if (receiver == USER13) { 111 | * | fl.log("Receiver USER13 hit"); 112 | | } 113 | | } 114 | | 115 | * | function _logCancellationReceiverCoverage( 116 | | address cancellationReceiver 117 | | ) internal { 118 | * | if (cancellationReceiver == USER0) { 119 | * | fl.log("CancellationReceiver USER0 hit"); 120 | | } 121 | * | if (cancellationReceiver == USER1) { 122 | * | fl.log("CancellationReceiver USER1 hit"); 123 | | } 124 | * | if (cancellationReceiver == USER2) { 125 | * | fl.log("CancellationReceiver USER2 hit"); 126 | | } 127 | * | if (cancellationReceiver == USER3) { 128 | * | fl.log("CancellationReceiver USER3 hit"); 129 | | } 130 | * | if (cancellationReceiver == USER4) { 131 | * | fl.log("CancellationReceiver USER4 hit"); 132 | | } 133 | * | if (cancellationReceiver == USER5) { 134 | * | fl.log("CancellationReceiver USER5 hit"); 135 | | } 136 | * | if (cancellationReceiver == USER6) { 137 | * | fl.log("CancellationReceiver USER6 hit"); 138 | | } 139 | * | if (cancellationReceiver == USER7) { 140 | * | fl.log("CancellationReceiver USER7 hit"); 141 | | } 142 | * | if (cancellationReceiver == USER8) { 143 | * | fl.log("CancellationReceiver USER8 hit"); 144 | | } 145 | * | if (cancellationReceiver == USER9) { 146 | * | fl.log("CancellationReceiver USER9 hit"); 147 | | } 148 | * | if (cancellationReceiver == USER10) { 149 | * | fl.log("CancellationReceiver USER10 hit"); 150 | | } 151 | * | if (cancellationReceiver == USER11) { 152 | * | fl.log("CancellationReceiver USER11 hit"); 153 | | } 154 | * | if (cancellationReceiver == USER12) { 155 | * | fl.log("CancellationReceiver USER12 hit"); 156 | | } 157 | * | if (cancellationReceiver == USER13) { 158 | * | fl.log("CancellationReceiver USER13 hit"); 159 | | } 160 | | } 161 | | 162 | * | function _logCallbackContractCoverage(address callbackContract) internal { 163 | * | if (callbackContract == address(0)) { 164 | | fl.log("CallbackContract is address(0)"); 165 | | } else { 166 | * | fl.log("CallbackContract is non-zero address"); 167 | | } 168 | | } 169 | | 170 | * | function _logUiFeeReceiverCoverage(address uiFeeReceiver) internal { 171 | * | if (uiFeeReceiver == address(0)) { 172 | * | fl.log("UiFeeReceiver is address(0)"); 173 | | } else { 174 | | fl.log("UiFeeReceiver is non-zero address"); 175 | | } 176 | | } 177 | | 178 | * | function _logInitialCollateralTokenCoverage( 179 | | address initialCollateralToken 180 | | ) internal { 181 | * | if (initialCollateralToken == address(WETH)) { 182 | * | fl.log("InitialCollateralToken is WETH"); 183 | | } 184 | * | if (initialCollateralToken == address(WBTC)) { 185 | * | fl.log("InitialCollateralToken is WBTC"); 186 | | } 187 | * | if (initialCollateralToken == address(USDC)) { 188 | * | fl.log("InitialCollateralToken is USDC"); 189 | | } 190 | * | if (initialCollateralToken == address(USDT)) { 191 | * | fl.log("InitialCollateralToken is USDT"); 192 | | } 193 | * | if (initialCollateralToken == address(SOL)) { 194 | | fl.log("InitialCollateralToken is SOL"); 195 | | } 196 | | } 197 | | 198 | * | function _logMarketCoverage(address market) internal { 199 | * | if (market == address(market_0_WETH_USDC)) { 200 | | fl.log("Market market_0_WETH_USDC hit"); 201 | | } 202 | | 203 | * | if (market == address(market_WBTC_WBTC_USDC)) { 204 | * | fl.log("Market market_WBTC_WBTC_USDC hit"); 205 | | } 206 | * | if (market == address(market_WETH_WETH_USDC)) { 207 | * | fl.log("Market market_WETH_WETH_USDC hit"); 208 | | } 209 | * | if (market == address(market_WETH_WETH_USDT)) { 210 | * | fl.log("Market market_WETH_WETH_USDT hit"); 211 | | } 212 | | } 213 | | 214 | * | function _logSwapPathCoverage(address[] memory swapPath) internal { 215 | * | if (swapPath.length == 0) { 216 | * | fl.log("SwapPath is empty"); 217 | | } 218 | * | if (swapPath.length == 1) { 219 | * | fl.log("SwapPath has 1 element"); 220 | | } 221 | * | if (swapPath.length == 2) { 222 | * | fl.log("SwapPath has 2 elements"); 223 | | } 224 | * | if (swapPath.length >= 3) { 225 | * | fl.log("SwapPath has 3 or more elements"); 226 | | } 227 | | } 228 | | 229 | * | function _logOrderTypeCoverage(Order.OrderType orderType) internal { 230 | * | if (orderType == Order.OrderType.MarketSwap) { 231 | * | fl.log("OrderType is MarketSwap"); 232 | | } 233 | * | if (orderType == Order.OrderType.LimitSwap) { 234 | * | fl.log("OrderType is LimitSwap"); 235 | | } 236 | * | if (orderType == Order.OrderType.MarketIncrease) { 237 | * | fl.log("OrderType is MarketIncrease"); 238 | | } 239 | * | if (orderType == Order.OrderType.LimitIncrease) { 240 | * | fl.log("OrderType is LimitIncrease"); 241 | | } 242 | * | if (orderType == Order.OrderType.MarketDecrease) { 243 | | fl.log("OrderType is MarketDecrease"); 244 | | } 245 | * | if (orderType == Order.OrderType.LimitDecrease) { 246 | | fl.log("OrderType is LimitDecrease"); 247 | | } 248 | * | if (orderType == Order.OrderType.StopLossDecrease) { 249 | * | fl.log("OrderType is StopLossDecrease"); 250 | | } 251 | * | if (orderType == Order.OrderType.Liquidation) { 252 | | fl.log("OrderType is Liquidation"); 253 | | } 254 | | } 255 | | 256 | * | function _logDecreasePositionSwapTypeCoverage( 257 | | Order.DecreasePositionSwapType decreasePositionSwapType 258 | | ) internal { 259 | * | if (decreasePositionSwapType == Order.DecreasePositionSwapType.NoSwap) { 260 | * | fl.log("DecreasePositionSwapType is NoSwap"); 261 | | } 262 | * | if ( 263 | * | decreasePositionSwapType == 264 | * | Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken 265 | | ) { 266 | | fl.log("DecreasePositionSwapType is SwapPnlTokenToCollateralToken"); 267 | | } 268 | * | if ( 269 | * | decreasePositionSwapType == 270 | * | Order.DecreasePositionSwapType.SwapCollateralTokenToPnlToken 271 | | ) { 272 | | fl.log("DecreasePositionSwapType is SwapCollateralTokenToPnlToken"); 273 | | } 274 | | } 275 | | 276 | * | function _logIsLongCoverage(bool isLong) internal { 277 | * | if (isLong) { 278 | * | fl.log("IsLong is true"); 279 | | } else { 280 | * | fl.log("IsLong is false"); 281 | | } 282 | | } 283 | | 284 | * | function _logShouldUnwrapNativeTokenCoverage( 285 | | bool shouldUnwrapNativeToken 286 | | ) internal { 287 | * | if (shouldUnwrapNativeToken) { 288 | | fl.log("ShouldUnwrapNativeToken is true"); 289 | | } else { 290 | * | fl.log("ShouldUnwrapNativeToken is false"); 291 | | } 292 | | } 293 | | 294 | * | function _logAutoCancelCoverage(bool autoCancel) internal { 295 | * | if (autoCancel) { 296 | * | fl.log("AutoCancel is true"); 297 | | } else { 298 | | fl.log("AutoCancel is false"); 299 | | } 300 | | } 301 | | 302 | * | function _logReferralCodeCoverage(bytes32 referralCode) internal { 303 | * | if (referralCode == bytes32(0)) { 304 | * | fl.log("ReferralCode is empty"); 305 | | } else { 306 | | fl.log("ReferralCode is non-empty"); 307 | | } 308 | | } 309 | | 310 | * | function _logSizeDeltaUsdCoverage(uint256 sizeDeltaUsd) internal { 311 | * | if (sizeDeltaUsd == 0) { 312 | | fl.log("SizeDeltaUsd is 0"); 313 | | } 314 | * | if (sizeDeltaUsd > 0 && sizeDeltaUsd <= 1e6) { 315 | | fl.log("SizeDeltaUsd is between 0 and 1e6"); 316 | | } 317 | * | if (sizeDeltaUsd > 1e6 && sizeDeltaUsd <= 1e12) { 318 | | fl.log("SizeDeltaUsd is between 1e6 and 1e12"); 319 | | } 320 | * | if (sizeDeltaUsd > 1e12 && sizeDeltaUsd <= 1e18) { 321 | | fl.log("SizeDeltaUsd is between 1e12 and 1e18"); 322 | | } 323 | * | if (sizeDeltaUsd > 1e18 && sizeDeltaUsd <= 1e24) { 324 | | fl.log("SizeDeltaUsd is between 1e18 and 1e24"); 325 | | } 326 | * | if (sizeDeltaUsd > 1e24) { 327 | * | fl.log("SizeDeltaUsd is greater than 1e24"); 328 | | } 329 | | } 330 | | 331 | * | function _logInitialCollateralDeltaAmountCoverage( 332 | | uint256 initialCollateralDeltaAmount 333 | | ) internal { 334 | * | if (initialCollateralDeltaAmount == 0) { 335 | * | fl.log("InitialCollateralDeltaAmount is 0"); 336 | | } 337 | * | if ( 338 | * | initialCollateralDeltaAmount > 0 && 339 | * | initialCollateralDeltaAmount <= 1e6 340 | | ) { 341 | * | fl.log("InitialCollateralDeltaAmount is between 0 and 1e6"); 342 | | } 343 | * | if ( 344 | * | initialCollateralDeltaAmount > 1e6 && 345 | * | initialCollateralDeltaAmount <= 1e12 346 | | ) { 347 | * | fl.log("InitialCollateralDeltaAmount is between 1e6 and 1e12"); 348 | | } 349 | * | if ( 350 | * | initialCollateralDeltaAmount > 1e12 && 351 | * | initialCollateralDeltaAmount <= 1e18 352 | | ) { 353 | * | fl.log("InitialCollateralDeltaAmount is between 1e12 and 1e18"); 354 | | } 355 | * | if ( 356 | * | initialCollateralDeltaAmount > 1e18 && 357 | * | initialCollateralDeltaAmount <= 1e24 358 | | ) { 359 | * | fl.log("InitialCollateralDeltaAmount is between 1e18 and 1e24"); 360 | | } 361 | * | if (initialCollateralDeltaAmount > 1e24) { 362 | | fl.log("InitialCollateralDeltaAmount is greater than 1e24"); 363 | | } 364 | | } 365 | | 366 | * | function _logTriggerPriceCoverage(uint256 triggerPrice) internal { 367 | * | if (triggerPrice == 0) { 368 | | fl.log("TriggerPrice is 0"); 369 | | } 370 | * | if (triggerPrice > 0 && triggerPrice <= 1e6) { 371 | | fl.log("TriggerPrice is between 0 and 1e6"); 372 | | } 373 | * | if (triggerPrice > 1e6 && triggerPrice <= 1e12) { 374 | | fl.log("TriggerPrice is between 1e6 and 1e12"); 375 | | } 376 | * | if (triggerPrice > 1e12 && triggerPrice <= 1e18) { 377 | * | fl.log("TriggerPrice is between 1e12 and 1e18"); 378 | | } 379 | * | if (triggerPrice > 1e18 && triggerPrice <= 1e24) { 380 | * | fl.log("TriggerPrice is between 1e18 and 1e24"); 381 | | } 382 | * | if (triggerPrice > 1e24) { 383 | * | fl.log("TriggerPrice is greater than 1e24"); 384 | | } 385 | | } 386 | | 387 | * | function _logAcceptablePriceCoverage(uint256 acceptablePrice) internal { 388 | * | if (acceptablePrice == 0) { 389 | * | fl.log("AcceptablePrice is 0"); 390 | | } 391 | * | if (acceptablePrice > 0 && acceptablePrice <= 1e6) { 392 | * | fl.log("AcceptablePrice is between 0 and 1e6"); 393 | | } 394 | * | if (acceptablePrice > 1e6 && acceptablePrice <= 1e12) { 395 | | fl.log("AcceptablePrice is between 1e6 and 1e12"); 396 | | } 397 | * | if (acceptablePrice > 1e12 && acceptablePrice <= 1e18) { 398 | | fl.log("AcceptablePrice is between 1e12 and 1e18"); 399 | | } 400 | * | if (acceptablePrice > 1e18 && acceptablePrice <= 1e24) { 401 | | fl.log("AcceptablePrice is between 1e18 and 1e24"); 402 | | } 403 | * | if (acceptablePrice > 1e24) { 404 | * | fl.log("AcceptablePrice is greater than 1e24"); 405 | | } 406 | | } 407 | | 408 | * | function _logExecutionFeeCoverage(uint256 executionFee) internal { 409 | * | if (executionFee == 0) { 410 | * | fl.log("ExecutionFee is 0"); 411 | | } 412 | * | if (executionFee > 0 && executionFee <= 1e6) { 413 | | fl.log("ExecutionFee is between 0 and 1e6"); 414 | | } 415 | * | if (executionFee > 1e6 && executionFee <= 1e12) { 416 | * | fl.log("ExecutionFee is between 1e6 and 1e12"); 417 | | } 418 | * | if (executionFee > 1e12 && executionFee <= 1e18) { 419 | | fl.log("ExecutionFee is between 1e12 and 1e18"); 420 | | } 421 | * | if (executionFee > 1e18 && executionFee <= 1e24) { 422 | | fl.log("ExecutionFee is between 1e18 and 1e24"); 423 | | } 424 | * | if (executionFee > 1e24) { 425 | | fl.log("ExecutionFee is greater than 1e24"); 426 | | } 427 | | } 428 | | 429 | * | function _logCallbackGasLimitCoverage(uint256 callbackGasLimit) internal { 430 | * | if (callbackGasLimit == 0) { 431 | | fl.log("CallbackGasLimit is 0"); 432 | | } 433 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 434 | * | fl.log("CallbackGasLimit is between 0 and 1e6"); 435 | | } 436 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 437 | | fl.log("CallbackGasLimit is between 1e6 and 1e12"); 438 | | } 439 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 440 | | fl.log("CallbackGasLimit is between 1e12 and 1e18"); 441 | | } 442 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 443 | | fl.log("CallbackGasLimit is between 1e18 and 1e24"); 444 | | } 445 | * | if (callbackGasLimit > 1e24) { 446 | | fl.log("CallbackGasLimit is greater than 1e24"); 447 | | } 448 | | } 449 | | 450 | * | function _logMinOutputAmountCoverage(uint256 minOutputAmount) internal { 451 | * | if (minOutputAmount == 0) { 452 | | fl.log("MinOutputAmount is 0"); 453 | | } 454 | * | if (minOutputAmount > 0 && minOutputAmount <= 1e6) { 455 | * | fl.log("MinOutputAmount is between 0 and 1e6"); 456 | | } 457 | * | if (minOutputAmount > 1e6 && minOutputAmount <= 1e12) { 458 | | fl.log("MinOutputAmount is between 1e6 and 1e12"); 459 | | } 460 | * | if (minOutputAmount > 1e12 && minOutputAmount <= 1e18) { 461 | | fl.log("MinOutputAmount is between 1e12 and 1e18"); 462 | | } 463 | * | if (minOutputAmount > 1e18 && minOutputAmount <= 1e24) { 464 | | fl.log("MinOutputAmount is between 1e18 and 1e24"); 465 | | } 466 | * | if (minOutputAmount > 1e24) { 467 | | fl.log("MinOutputAmount is greater than 1e24"); 468 | | } 469 | | } 470 | | 471 | * | function _logKeyCoverage(bytes32 key) internal { 472 | * | if (key == bytes32(0)) { 473 | | fl.log("Key is empty"); 474 | | } else { 475 | * | fl.log("Key is non-empty"); 476 | | } 477 | | } 478 | | 479 | * | function _logUpdatedAtCoverage(uint256 updatedAt) internal { 480 | * | if (updatedAt == 0) { 481 | | fl.log("UpdatedAt is 0"); 482 | | } else { 483 | * | fl.log("UpdatedAt is non-zero"); 484 | | } 485 | | } 486 | | 487 | * | function _logUserCoverage(address user) internal { 488 | * | if (user == USER0) { 489 | * | fl.log("User USER0 hit"); 490 | | } 491 | * | if (user == USER1) { 492 | * | fl.log("User USER1 hit"); 493 | | } 494 | * | if (user == USER2) { 495 | * | fl.log("User USER2 hit"); 496 | | } 497 | * | if (user == USER3) { 498 | * | fl.log("User USER3 hit"); 499 | | } 500 | * | if (user == USER4) { 501 | * | fl.log("User USER4 hit"); 502 | | } 503 | * | if (user == USER5) { 504 | * | fl.log("User USER5 hit"); 505 | | } 506 | * | if (user == USER6) { 507 | * | fl.log("User USER6 hit"); 508 | | } 509 | * | if (user == USER7) { 510 | * | fl.log("User USER7 hit"); 511 | | } 512 | * | if (user == USER8) { 513 | * | fl.log("User USER8 hit"); 514 | | } 515 | * | if (user == USER9) { 516 | * | fl.log("User USER9 hit"); 517 | | } 518 | * | if (user == USER10) { 519 | * | fl.log("User USER10 hit"); 520 | | } 521 | * | if (user == USER11) { 522 | * | fl.log("User USER11 hit"); 523 | | } 524 | * | if (user == USER12) { 525 | * | fl.log("User USER12 hit"); 526 | | } 527 | * | if (user == USER13) { 528 | * | fl.log("User USER13 hit"); 529 | | } 530 | | } 531 | | 532 | * | function _logHandlerTypeCoverage(bytes32 handlerType) internal { 533 | * | if (handlerType == bytes32(0)) { 534 | | fl.log("HandlerType is empty"); 535 | | } else { 536 | * | fl.log("HandlerType is non-empty"); 537 | | } 538 | | } 539 | | 540 | * | function _logAmountSentCoverage(uint256 amountSent) internal { 541 | * | if (amountSent == 0) { 542 | * | fl.log("AmountSent is 0"); 543 | | } 544 | * | if (amountSent > 0 && amountSent <= 1e6) { 545 | * | fl.log("AmountSent is between 0 and 1e6"); 546 | | } 547 | * | if (amountSent > 1e6 && amountSent <= 1e12) { 548 | * | fl.log("AmountSent is between 1e6 and 1e12"); 549 | | } 550 | * | if (amountSent > 1e12 && amountSent <= 1e18) { 551 | * | fl.log("AmountSent is between 1e12 and 1e18"); 552 | | } 553 | * | if (amountSent > 1e18 && amountSent <= 1e24) { 554 | * | fl.log("AmountSent is between 1e18 and 1e24"); 555 | | } 556 | * | if (amountSent > 1e24) { 557 | | fl.log("AmountSent is greater than 1e24"); 558 | | } 559 | | } 560 | | 561 | * | function _logIsCloseCoverage(bool isClose) internal { 562 | * | if (isClose) { 563 | * | fl.log("IsClose is true"); 564 | | } else { 565 | * | fl.log("IsClose is false"); 566 | | } 567 | | } 568 | | } 569 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/DecreasePositionInfoCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract DecreasePositionInfoCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ DECREASE POSITION 10 | | // __^ __( \.__) ) GET POSITION INFO 11 | | // (@)<_____>__(_____)____/ COVERAGE 12 | | 13 | | function _checkDecreaseOrderAndGetPositionCoverage( 14 | | Position.Props memory position 15 | | ) internal { 16 | | _logPositionAccountCoverage_decreasePosition( 17 | | position.addresses.account 18 | | ); 19 | | _logPositionMarketCoverage_decreasePosition(position.addresses.market); 20 | | _logPositionCollateralTokenCoverage_decreasePosition( 21 | | position.addresses.collateralToken 22 | | ); 23 | | _logPositionSizeInUsdCoverage_decreasePosition( 24 | | position.numbers.sizeInUsd 25 | | ); 26 | | _logPositionSizeInTokensCoverage_decreasePosition( 27 | | position.numbers.sizeInTokens 28 | | ); 29 | | _logPositionCollateralAmountCoverage_decreasePosition( 30 | | position.numbers.collateralAmount 31 | | ); 32 | | _logPositionBorrowingFactorCoverage_decreasePosition( 33 | | position.numbers.borrowingFactor 34 | | ); 35 | | _logPositionFundingFeeAmountPerSizeCoverage_decreasePosition( 36 | | position.numbers.fundingFeeAmountPerSize 37 | | ); 38 | | _logPositionLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 39 | | position.numbers.longTokenClaimableFundingAmountPerSize 40 | | ); 41 | | _logPositionShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 42 | | position.numbers.shortTokenClaimableFundingAmountPerSize 43 | | ); 44 | | _logPositionIncreasedAtBlockCoverage_decreasePosition( 45 | | position.numbers.increasedAtBlock 46 | | ); 47 | | _logPositionDecreasedAtBlockCoverage_decreasePosition( 48 | | position.numbers.decreasedAtBlock 49 | | ); 50 | | _logPositionIncreasedAtTimeCoverage_decreasePosition( 51 | | position.numbers.increasedAtTime 52 | | ); 53 | | _logPositionDecreasedAtTimeCoverage_decreasePosition( 54 | | position.numbers.decreasedAtTime 55 | | ); 56 | | _logPositionIsLongCoverage_decreasePosition(position.flags.isLong); 57 | | } 58 | | 59 | | function _logPositionAccountCoverage_decreasePosition( 60 | | address account 61 | | ) internal { 62 | | if (account == USER0) { 63 | | fl.log("PositionFees account USER0 hit"); 64 | | } 65 | | if (account == USER1) { 66 | | fl.log("PositionFees account USER1 hit"); 67 | | } 68 | | if (account == USER2) { 69 | | fl.log("PositionFees account USER2 hit"); 70 | | } 71 | | if (account == USER3) { 72 | | fl.log("PositionFees account USER3 hit"); 73 | | } 74 | | if (account == USER4) { 75 | | fl.log("PositionFees account USER4 hit"); 76 | | } 77 | | if (account == USER5) { 78 | | fl.log("PositionFees account USER5 hit"); 79 | | } 80 | | if (account == USER6) { 81 | | fl.log("PositionFees account USER6 hit"); 82 | | } 83 | | if (account == USER7) { 84 | | fl.log("PositionFees account USER7 hit"); 85 | | } 86 | | if (account == USER8) { 87 | | fl.log("PositionFees account USER8 hit"); 88 | | } 89 | | if (account == USER9) { 90 | | fl.log("PositionFees account USER9 hit"); 91 | | } 92 | | if (account == USER10) { 93 | | fl.log("PositionFees account USER10 hit"); 94 | | } 95 | | if (account == USER11) { 96 | | fl.log("PositionFees account USER11 hit"); 97 | | } 98 | | if (account == USER12) { 99 | | fl.log("PositionFees account USER12 hit"); 100 | | } 101 | | if (account == USER13) { 102 | | fl.log("PositionFees account USER13 hit"); 103 | | } 104 | | } 105 | | function _logPositionMarketCoverage_decreasePosition( 106 | | address market 107 | | ) internal { 108 | | if (market == address(market_0_WETH_USDC)) { 109 | | fl.log("Position market market_0_WETH_USDC hit"); 110 | | } 111 | | 112 | | if (market == address(market_WBTC_WBTC_USDC)) { 113 | | fl.log("Position market market_WBTC_WBTC_USDC hit"); 114 | | } 115 | | if (market == address(market_WETH_WETH_USDC)) { 116 | | fl.log("Position market market_WETH_WETH_USDC hit"); 117 | | } 118 | | if (market == address(market_WETH_WETH_USDT)) { 119 | | fl.log("Position market market_WETH_WETH_USDT hit"); 120 | | } 121 | | } 122 | | 123 | | function _logPositionCollateralTokenCoverage_decreasePosition( 124 | | address collateralToken 125 | | ) internal { 126 | | if (collateralToken == address(WETH)) { 127 | | fl.log("Position collateralToken is WETH"); 128 | | } 129 | | if (collateralToken == address(WBTC)) { 130 | | fl.log("Position collateralToken is WBTC"); 131 | | } 132 | | if (collateralToken == address(USDC)) { 133 | | fl.log("Position collateralToken is USDC"); 134 | | } 135 | | if (collateralToken == address(USDT)) { 136 | | fl.log("Position collateralToken is USDT"); 137 | | } 138 | | if (collateralToken == address(SOL)) { 139 | | fl.log("Position collateralToken is SOL"); 140 | | } 141 | | } 142 | | 143 | | function _logPositionSizeInUsdCoverage_decreasePosition( 144 | | uint256 sizeInUsd 145 | | ) internal { 146 | | if (sizeInUsd == 0) { 147 | | fl.log("Position sizeInUsd is 0"); 148 | | } 149 | | if (sizeInUsd > 0 && sizeInUsd <= 1e6) { 150 | | fl.log("Position sizeInUsd is between 0 and 1e6"); 151 | | } 152 | | if (sizeInUsd > 1e6 && sizeInUsd <= 1e12) { 153 | | fl.log("Position sizeInUsd is between 1e6 and 1e12"); 154 | | } 155 | | if (sizeInUsd > 1e12 && sizeInUsd <= 1e18) { 156 | | fl.log("Position sizeInUsd is between 1e12 and 1e18"); 157 | | } 158 | | if (sizeInUsd > 1e18 && sizeInUsd <= 1e24) { 159 | | fl.log("Position sizeInUsd is between 1e18 and 1e24"); 160 | | } 161 | | if (sizeInUsd > 1e24) { 162 | | fl.log("Position sizeInUsd is greater than 1e24"); 163 | | } 164 | | } 165 | | 166 | | function _logPositionSizeInTokensCoverage_decreasePosition( 167 | | uint256 sizeInTokens 168 | | ) internal { 169 | | if (sizeInTokens == 0) { 170 | | fl.log("Position sizeInTokens is 0"); 171 | | } 172 | | if (sizeInTokens > 0 && sizeInTokens <= 1e6) { 173 | | fl.log("Position sizeInTokens is between 0 and 1e6"); 174 | | } 175 | | if (sizeInTokens > 1e6 && sizeInTokens <= 1e12) { 176 | | fl.log("Position sizeInTokens is between 1e6 and 1e12"); 177 | | } 178 | | if (sizeInTokens > 1e12 && sizeInTokens <= 1e18) { 179 | | fl.log("Position sizeInTokens is between 1e12 and 1e18"); 180 | | } 181 | | if (sizeInTokens > 1e18 && sizeInTokens <= 1e24) { 182 | | fl.log("Position sizeInTokens is between 1e18 and 1e24"); 183 | | } 184 | | if (sizeInTokens > 1e24) { 185 | | fl.log("Position sizeInTokens is greater than 1e24"); 186 | | } 187 | | } 188 | | 189 | | function _logPositionCollateralAmountCoverage_decreasePosition( 190 | | uint256 collateralAmount 191 | | ) internal { 192 | | if (collateralAmount == 0) { 193 | | fl.log("Position collateralAmount is 0"); 194 | | } 195 | | if (collateralAmount > 0 && collateralAmount <= 1e6) { 196 | | fl.log("Position collateralAmount is between 0 and 1e6"); 197 | | } 198 | | if (collateralAmount > 1e6 && collateralAmount <= 1e12) { 199 | | fl.log("Position collateralAmount is between 1e6 and 1e12"); 200 | | } 201 | | if (collateralAmount > 1e12 && collateralAmount <= 1e18) { 202 | | fl.log("Position collateralAmount is between 1e12 and 1e18"); 203 | | } 204 | | if (collateralAmount > 1e18 && collateralAmount <= 1e24) { 205 | | fl.log("Position collateralAmount is between 1e18 and 1e24"); 206 | | } 207 | | if (collateralAmount > 1e24) { 208 | | fl.log("Position collateralAmount is greater than 1e24"); 209 | | } 210 | | } 211 | | 212 | | function _logPositionBorrowingFactorCoverage_decreasePosition( 213 | | uint256 borrowingFactor 214 | | ) internal { 215 | | if (borrowingFactor == 0) { 216 | | fl.log("Position borrowingFactor is 0"); 217 | | } 218 | | if (borrowingFactor > 0 && borrowingFactor <= 1e6) { 219 | | fl.log("Position borrowingFactor is between 0 and 1e6"); 220 | | } 221 | | if (borrowingFactor > 1e6 && borrowingFactor <= 1e12) { 222 | | fl.log("Position borrowingFactor is between 1e6 and 1e12"); 223 | | } 224 | | if (borrowingFactor > 1e12 && borrowingFactor <= 1e18) { 225 | | fl.log("Position borrowingFactor is between 1e12 and 1e18"); 226 | | } 227 | | if (borrowingFactor > 1e18 && borrowingFactor <= 1e24) { 228 | | fl.log("Position borrowingFactor is between 1e18 and 1e24"); 229 | | } 230 | | if (borrowingFactor > 1e24) { 231 | | fl.log("Position borrowingFactor is greater than 1e24"); 232 | | } 233 | | } 234 | | 235 | | function _logPositionFundingFeeAmountPerSizeCoverage_decreasePosition( 236 | | uint256 fundingFeeAmountPerSize 237 | | ) internal { 238 | | if (fundingFeeAmountPerSize == 0) { 239 | | fl.log("Position fundingFeeAmountPerSize is 0"); 240 | | } 241 | | if (fundingFeeAmountPerSize > 0 && fundingFeeAmountPerSize <= 1e6) { 242 | | fl.log("Position fundingFeeAmountPerSize is between 0 and 1e6"); 243 | | } 244 | | if (fundingFeeAmountPerSize > 1e6 && fundingFeeAmountPerSize <= 1e12) { 245 | | fl.log("Position fundingFeeAmountPerSize is between 1e6 and 1e12"); 246 | | } 247 | | if (fundingFeeAmountPerSize > 1e12 && fundingFeeAmountPerSize <= 1e18) { 248 | | fl.log("Position fundingFeeAmountPerSize is between 1e12 and 1e18"); 249 | | } 250 | | if (fundingFeeAmountPerSize > 1e18 && fundingFeeAmountPerSize <= 1e24) { 251 | | fl.log("Position fundingFeeAmountPerSize is between 1e18 and 1e24"); 252 | | } 253 | | if (fundingFeeAmountPerSize > 1e24) { 254 | | fl.log("Position fundingFeeAmountPerSize is greater than 1e24"); 255 | | } 256 | | } 257 | | 258 | | function _logPositionLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 259 | | uint256 longTokenClaimableFundingAmountPerSize 260 | | ) internal { 261 | | if (longTokenClaimableFundingAmountPerSize == 0) { 262 | | fl.log("Position longTokenClaimableFundingAmountPerSize is 0"); 263 | | } 264 | | if ( 265 | | longTokenClaimableFundingAmountPerSize > 0 && 266 | | longTokenClaimableFundingAmountPerSize <= 1e6 267 | | ) { 268 | | fl.log( 269 | | "Position longTokenClaimableFundingAmountPerSize is between 0 and 1e6" 270 | | ); 271 | | } 272 | | if ( 273 | | longTokenClaimableFundingAmountPerSize > 1e6 && 274 | | longTokenClaimableFundingAmountPerSize <= 1e12 275 | | ) { 276 | | fl.log( 277 | | "Position longTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 278 | | ); 279 | | } 280 | | if ( 281 | | longTokenClaimableFundingAmountPerSize > 1e12 && 282 | | longTokenClaimableFundingAmountPerSize <= 1e18 283 | | ) { 284 | | fl.log( 285 | | "Position longTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 286 | | ); 287 | | } 288 | | if ( 289 | | longTokenClaimableFundingAmountPerSize > 1e18 && 290 | | longTokenClaimableFundingAmountPerSize <= 1e24 291 | | ) { 292 | | fl.log( 293 | | "Position longTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 294 | | ); 295 | | } 296 | | if (longTokenClaimableFundingAmountPerSize > 1e24) { 297 | | fl.log( 298 | | "Position longTokenClaimableFundingAmountPerSize is greater than 1e24" 299 | | ); 300 | | } 301 | | } 302 | | 303 | | function _logPositionShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 304 | | uint256 shortTokenClaimableFundingAmountPerSize 305 | | ) internal { 306 | | if (shortTokenClaimableFundingAmountPerSize == 0) { 307 | | fl.log("Position shortTokenClaimableFundingAmountPerSize is 0"); 308 | | } 309 | | if ( 310 | | shortTokenClaimableFundingAmountPerSize > 0 && 311 | | shortTokenClaimableFundingAmountPerSize <= 1e6 312 | | ) { 313 | | fl.log( 314 | | "Position shortTokenClaimableFundingAmountPerSize is between 0 and 1e6" 315 | | ); 316 | | } 317 | | if ( 318 | | shortTokenClaimableFundingAmountPerSize > 1e6 && 319 | | shortTokenClaimableFundingAmountPerSize <= 1e12 320 | | ) { 321 | | fl.log( 322 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 323 | | ); 324 | | } 325 | | if ( 326 | | shortTokenClaimableFundingAmountPerSize > 1e12 && 327 | | shortTokenClaimableFundingAmountPerSize <= 1e18 328 | | ) { 329 | | fl.log( 330 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 331 | | ); 332 | | } 333 | | if ( 334 | | shortTokenClaimableFundingAmountPerSize > 1e18 && 335 | | shortTokenClaimableFundingAmountPerSize <= 1e24 336 | | ) { 337 | | fl.log( 338 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 339 | | ); 340 | | } 341 | | if (shortTokenClaimableFundingAmountPerSize > 1e24) { 342 | | fl.log( 343 | | "Position shortTokenClaimableFundingAmountPerSize is greater than 1e24" 344 | | ); 345 | | } 346 | | } 347 | | 348 | | function _logPositionIncreasedAtBlockCoverage_decreasePosition( 349 | | uint256 increasedAtBlock 350 | | ) internal { 351 | | if (increasedAtBlock == 0) { 352 | | fl.log("Position increasedAtBlock is 0"); 353 | | } else { 354 | | fl.log("Position increasedAtBlock is non-zero"); 355 | | } 356 | | } 357 | | 358 | | function _logPositionDecreasedAtBlockCoverage_decreasePosition( 359 | | uint256 decreasedAtBlock 360 | | ) internal { 361 | | if (decreasedAtBlock == 0) { 362 | | fl.log("Position decreasedAtBlock is 0"); 363 | | } else { 364 | | fl.log("Position decreasedAtBlock is non-zero"); 365 | | } 366 | | } 367 | | 368 | | function _logPositionIncreasedAtTimeCoverage_decreasePosition( 369 | | uint256 increasedAtTime 370 | | ) internal { 371 | | if (increasedAtTime == 0) { 372 | | fl.log("Position increasedAtTime is 0"); 373 | | } else { 374 | | fl.log("Position increasedAtTime is non-zero"); 375 | | } 376 | | } 377 | | 378 | | function _logPositionDecreasedAtTimeCoverage_decreasePosition( 379 | | uint256 decreasedAtTime 380 | | ) internal { 381 | | if (decreasedAtTime == 0) { 382 | | fl.log("Position decreasedAtTime is 0"); 383 | | } else { 384 | | fl.log("Position decreasedAtTime is non-zero"); 385 | | } 386 | | } 387 | | 388 | | function _logPositionIsLongCoverage_decreasePosition(bool isLong) internal { 389 | | if (isLong) { 390 | | fl.log("Position isLong is true"); 391 | | } else { 392 | | fl.log("Position isLong is false"); 393 | | } 394 | | } 395 | | 396 | | function _checkDecreaseOrderAndGetPositionInfoCoverage( 397 | | ReaderUtils.PositionInfo memory positionInfo 398 | | ) internal { 399 | | // PositionFees 400 | | _logPositionFeesReferralCodeCoverage_decreasePosition( 401 | | positionInfo.fees.referral.referralCode 402 | | ); 403 | | _logPositionFeesAffiliateCoverage_decreasePosition( 404 | | positionInfo.fees.referral.affiliate 405 | | ); 406 | | _logPositionFeesTraderCoverage_decreasePosition( 407 | | positionInfo.fees.referral.trader 408 | | ); 409 | | _logPositionFeesTotalRebateFactorCoverage_decreasePosition( 410 | | positionInfo.fees.referral.totalRebateFactor 411 | | ); 412 | | _logPositionFeesTraderDiscountFactorCoverage_decreasePosition( 413 | | positionInfo.fees.referral.traderDiscountFactor 414 | | ); 415 | | _logPositionFeesTotalRebateAmountCoverage_decreasePosition( 416 | | positionInfo.fees.referral.totalRebateAmount 417 | | ); 418 | | _logPositionFeesTraderDiscountAmountCoverage_decreasePosition( 419 | | positionInfo.fees.referral.traderDiscountAmount 420 | | ); 421 | | _logPositionFeesAffiliateRewardAmountCoverage_decreasePosition( 422 | | positionInfo.fees.referral.affiliateRewardAmount 423 | | ); 424 | | _logPositionFeesFundingFeeAmountCoverage_decreasePosition( 425 | | positionInfo.fees.funding.fundingFeeAmount 426 | | ); 427 | | _logPositionFeesClaimableLongTokenAmountCoverage_decreasePosition( 428 | | positionInfo.fees.funding.claimableLongTokenAmount 429 | | ); 430 | | _logPositionFeesClaimableShortTokenAmountCoverage_decreasePosition( 431 | | positionInfo.fees.funding.claimableShortTokenAmount 432 | | ); 433 | | _logPositionFeesLatestFundingFeeAmountPerSizeCoverage_decreasePosition( 434 | | positionInfo.fees.funding.latestFundingFeeAmountPerSize 435 | | ); 436 | | _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 437 | | positionInfo 438 | | .fees 439 | | .funding 440 | | .latestLongTokenClaimableFundingAmountPerSize 441 | | ); 442 | | _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 443 | | positionInfo 444 | | .fees 445 | | .funding 446 | | .latestShortTokenClaimableFundingAmountPerSize 447 | | ); 448 | | _logPositionFeesBorrowingFeeUsdCoverage_decreasePosition( 449 | | positionInfo.fees.borrowing.borrowingFeeUsd 450 | | ); 451 | | _logPositionFeesBorrowingFeeAmountCoverage_decreasePosition( 452 | | positionInfo.fees.borrowing.borrowingFeeAmount 453 | | ); 454 | | _logPositionFeesBorrowingFeeReceiverFactorCoverage_decreasePosition( 455 | | positionInfo.fees.borrowing.borrowingFeeReceiverFactor 456 | | ); 457 | | _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage_decreasePosition( 458 | | positionInfo.fees.borrowing.borrowingFeeAmountForFeeReceiver 459 | | ); 460 | | _logPositionFeesUiFeeReceiverCoverage_decreasePosition( 461 | | positionInfo.fees.ui.uiFeeReceiver 462 | | ); 463 | | _logPositionFeesUiFeeReceiverFactorCoverage_decreasePosition( 464 | | positionInfo.fees.ui.uiFeeReceiverFactor 465 | | ); 466 | | _logPositionFeesUiFeeAmountCoverage_decreasePosition( 467 | | positionInfo.fees.ui.uiFeeAmount 468 | | ); 469 | | _logPositionFeesCollateralTokenPriceCoverage_decreasePosition( 470 | | positionInfo.fees.collateralTokenPrice.max 471 | | ); 472 | | 473 | | _logPositionFeesPositionFeeFactorCoverage_decreasePosition( 474 | | positionInfo.fees.positionFeeFactor 475 | | ); 476 | | _logPositionFeesProtocolFeeAmountCoverage_decreasePosition( 477 | | positionInfo.fees.protocolFeeAmount 478 | | ); 479 | | _logPositionFeesPositionFeeReceiverFactorCoverage_decreasePosition( 480 | | positionInfo.fees.positionFeeReceiverFactor 481 | | ); 482 | | _logPositionFeesFeeReceiverAmountCoverage_decreasePosition( 483 | | positionInfo.fees.feeReceiverAmount 484 | | ); 485 | | _logPositionFeesFeeAmountForPoolCoverage_decreasePosition( 486 | | positionInfo.fees.feeAmountForPool 487 | | ); 488 | | _logPositionFeesPositionFeeAmountForPoolCoverage_decreasePosition( 489 | | positionInfo.fees.positionFeeAmountForPool 490 | | ); 491 | | _logPositionFeesPositionFeeAmountCoverage_decreasePosition( 492 | | positionInfo.fees.positionFeeAmount 493 | | ); 494 | | _logPositionFeesTotalCostAmountExcludingFundingCoverage_decreasePosition( 495 | | positionInfo.fees.totalCostAmountExcludingFunding 496 | | ); 497 | | _logPositionFeesTotalCostAmountCoverage_decreasePosition( 498 | | positionInfo.fees.totalCostAmount 499 | | ); 500 | | 501 | | // ExecutionPriceResult 502 | | _logExecutionPriceResultPriceImpactUsdCoverage_decreasePosition( 503 | | positionInfo.executionPriceResult.priceImpactUsd 504 | | ); 505 | | _logExecutionPriceResultPriceImpactDiffUsdCoverage_decreasePosition( 506 | | positionInfo.executionPriceResult.priceImpactDiffUsd 507 | | ); 508 | | _logExecutionPriceResultExecutionPriceCoverage_decreasePosition( 509 | | positionInfo.executionPriceResult.executionPrice 510 | | ); 511 | | 512 | | _logPositionInfoBasePnlUsdCoverage_decreasePosition( 513 | | positionInfo.basePnlUsd 514 | | ); 515 | | _logPositionInfoUncappedBasePnlUsdCoverage_decreasePosition( 516 | | positionInfo.uncappedBasePnlUsd 517 | | ); 518 | | _logPositionInfoPnlAfterPriceImpactUsdCoverage_decreasePosition( 519 | | positionInfo.pnlAfterPriceImpactUsd 520 | | ); 521 | | } 522 | | 523 | | function _logPositionFeesReferralCodeCoverage_decreasePosition( 524 | | bytes32 referralCode 525 | | ) internal { 526 | | if (referralCode == bytes32(0)) { 527 | | fl.log("PositionFees referralCode is empty"); 528 | | } else { 529 | | fl.log("PositionFees referralCode is non-empty"); 530 | | } 531 | | } 532 | | 533 | | function _logPositionFeesAffiliateCoverage_decreasePosition( 534 | | address affiliate 535 | | ) internal { 536 | | if (affiliate == address(0)) { 537 | | fl.log("PositionFees affiliate is address(0)"); 538 | | } else { 539 | | fl.log("PositionFees affiliate is non-zero address"); 540 | | } 541 | | } 542 | | 543 | | function _logPositionFeesTraderCoverage_decreasePosition( 544 | | address trader 545 | | ) internal { 546 | | if (trader == USER0) { 547 | | fl.log("PositionFees trader USER0 hit"); 548 | | } 549 | | if (trader == USER1) { 550 | | fl.log("PositionFees trader USER1 hit"); 551 | | } 552 | | if (trader == USER2) { 553 | | fl.log("PositionFees trader USER2 hit"); 554 | | } 555 | | if (trader == USER3) { 556 | | fl.log("PositionFees trader USER3 hit"); 557 | | } 558 | | if (trader == USER4) { 559 | | fl.log("PositionFees trader USER4 hit"); 560 | | } 561 | | if (trader == USER5) { 562 | | fl.log("PositionFees trader USER5 hit"); 563 | | } 564 | | if (trader == USER6) { 565 | | fl.log("PositionFees trader USER6 hit"); 566 | | } 567 | | if (trader == USER7) { 568 | | fl.log("PositionFees trader USER7 hit"); 569 | | } 570 | | if (trader == USER8) { 571 | | fl.log("PositionFees trader USER8 hit"); 572 | | } 573 | | if (trader == USER9) { 574 | | fl.log("PositionFees trader USER9 hit"); 575 | | } 576 | | if (trader == USER10) { 577 | | fl.log("PositionFees trader USER10 hit"); 578 | | } 579 | | if (trader == USER11) { 580 | | fl.log("PositionFees trader USER11 hit"); 581 | | } 582 | | if (trader == USER12) { 583 | | fl.log("PositionFees trader USER12 hit"); 584 | | } 585 | | if (trader == USER13) { 586 | | fl.log("PositionFees trader USER13 hit"); 587 | | } 588 | | } 589 | | 590 | | function _logPositionFeesTotalRebateFactorCoverage_decreasePosition( 591 | | uint256 totalRebateFactor 592 | | ) internal { 593 | | if (totalRebateFactor == 0) { 594 | | fl.log("PositionFees totalRebateFactor is 0"); 595 | | } 596 | | if (totalRebateFactor > 0 && totalRebateFactor <= 1e6) { 597 | | fl.log("PositionFees totalRebateFactor is between 0 and 1e6"); 598 | | } 599 | | if (totalRebateFactor > 1e6 && totalRebateFactor <= 1e12) { 600 | | fl.log("PositionFees totalRebateFactor is between 1e6 and 1e12"); 601 | | } 602 | | if (totalRebateFactor > 1e12 && totalRebateFactor <= 1e18) { 603 | | fl.log("PositionFees totalRebateFactor is between 1e12 and 1e18"); 604 | | } 605 | | if (totalRebateFactor > 1e18 && totalRebateFactor <= 1e24) { 606 | | fl.log("PositionFees totalRebateFactor is between 1e18 and 1e24"); 607 | | } 608 | | if (totalRebateFactor > 1e24) { 609 | | fl.log("PositionFees totalRebateFactor is greater than 1e24"); 610 | | } 611 | | } 612 | | 613 | | function _logPositionFeesTraderDiscountFactorCoverage_decreasePosition( 614 | | uint256 traderDiscountFactor 615 | | ) internal { 616 | | if (traderDiscountFactor == 0) { 617 | | fl.log("PositionFees traderDiscountFactor is 0"); 618 | | } 619 | | if (traderDiscountFactor > 0 && traderDiscountFactor <= 1e6) { 620 | | fl.log("PositionFees traderDiscountFactor is between 0 and 1e6"); 621 | | } 622 | | if (traderDiscountFactor > 1e6 && traderDiscountFactor <= 1e12) { 623 | | fl.log("PositionFees traderDiscountFactor is between 1e6 and 1e12"); 624 | | } 625 | | if (traderDiscountFactor > 1e12 && traderDiscountFactor <= 1e18) { 626 | | fl.log( 627 | | "PositionFees traderDiscountFactor is between 1e12 and 1e18" 628 | | ); 629 | | } 630 | | if (traderDiscountFactor > 1e18 && traderDiscountFactor <= 1e24) { 631 | | fl.log( 632 | | "PositionFees traderDiscountFactor is between 1e18 and 1e24" 633 | | ); 634 | | } 635 | | if (traderDiscountFactor > 1e24) { 636 | | fl.log("PositionFees traderDiscountFactor is greater than 1e24"); 637 | | } 638 | | } 639 | | 640 | | function _logPositionFeesTotalRebateAmountCoverage_decreasePosition( 641 | | uint256 totalRebateAmount 642 | | ) internal { 643 | | if (totalRebateAmount == 0) { 644 | | fl.log("PositionFees totalRebateAmount is 0"); 645 | | } 646 | | if (totalRebateAmount > 0 && totalRebateAmount <= 1e6) { 647 | | fl.log("PositionFees totalRebateAmount is between 0 and 1e6"); 648 | | } 649 | | if (totalRebateAmount > 1e6 && totalRebateAmount <= 1e12) { 650 | | fl.log("PositionFees totalRebateAmount is between 1e6 and 1e12"); 651 | | } 652 | | if (totalRebateAmount > 1e12 && totalRebateAmount <= 1e18) { 653 | | fl.log("PositionFees totalRebateAmount is between 1e12 and 1e18"); 654 | | } 655 | | if (totalRebateAmount > 1e18 && totalRebateAmount <= 1e24) { 656 | | fl.log("PositionFees totalRebateAmount is between 1e18 and 1e24"); 657 | | } 658 | | if (totalRebateAmount > 1e24) { 659 | | fl.log("PositionFees totalRebateAmount is greater than 1e24"); 660 | | } 661 | | } 662 | | 663 | | function _logPositionFeesTraderDiscountAmountCoverage_decreasePosition( 664 | | uint256 traderDiscountAmount 665 | | ) internal { 666 | | if (traderDiscountAmount == 0) { 667 | | fl.log("PositionFees traderDiscountAmount is 0"); 668 | | } 669 | | if (traderDiscountAmount > 0 && traderDiscountAmount <= 1e6) { 670 | | fl.log("PositionFees traderDiscountAmount is between 0 and 1e6"); 671 | | } 672 | | if (traderDiscountAmount > 1e6 && traderDiscountAmount <= 1e12) { 673 | | fl.log("PositionFees traderDiscountAmount is between 1e6 and 1e12"); 674 | | } 675 | | if (traderDiscountAmount > 1e12 && traderDiscountAmount <= 1e18) { 676 | | fl.log( 677 | | "PositionFees traderDiscountAmount is between 1e12 and 1e18" 678 | | ); 679 | | } 680 | | if (traderDiscountAmount > 1e18 && traderDiscountAmount <= 1e24) { 681 | | fl.log( 682 | | "PositionFees traderDiscountAmount is between 1e18 and 1e24" 683 | | ); 684 | | } 685 | | if (traderDiscountAmount > 1e24) { 686 | | fl.log("PositionFees traderDiscountAmount is greater than 1e24"); 687 | | } 688 | | } 689 | | 690 | | function _logPositionFeesAffiliateRewardAmountCoverage_decreasePosition( 691 | | uint256 affiliateRewardAmount 692 | | ) internal { 693 | | if (affiliateRewardAmount == 0) { 694 | | fl.log("PositionFees affiliateRewardAmount is 0"); 695 | | } 696 | | if (affiliateRewardAmount > 0 && affiliateRewardAmount <= 1e6) { 697 | | fl.log("PositionFees affiliateRewardAmount is between 0 and 1e6"); 698 | | } 699 | | if (affiliateRewardAmount > 1e6 && affiliateRewardAmount <= 1e12) { 700 | | fl.log( 701 | | "PositionFees affiliateRewardAmount is between 1e6 and 1e12" 702 | | ); 703 | | } 704 | | if (affiliateRewardAmount > 1e12 && affiliateRewardAmount <= 1e18) { 705 | | fl.log( 706 | | "PositionFees affiliateRewardAmount is between 1e12 and 1e18" 707 | | ); 708 | | } 709 | | if (affiliateRewardAmount > 1e18 && affiliateRewardAmount <= 1e24) { 710 | | fl.log( 711 | | "PositionFees affiliateRewardAmount is between 1e18 and 1e24" 712 | | ); 713 | | } 714 | | if (affiliateRewardAmount > 1e24) { 715 | | fl.log("PositionFees affiliateRewardAmount is greater than 1e24"); 716 | | } 717 | | } 718 | | 719 | | function _logPositionFeesFundingFeeAmountCoverage_decreasePosition( 720 | | uint256 fundingFeeAmount 721 | | ) internal { 722 | | if (fundingFeeAmount == 0) { 723 | | fl.log("PositionFees fundingFeeAmount is 0"); 724 | | } 725 | | if (fundingFeeAmount > 0 && fundingFeeAmount <= 1e6) { 726 | | fl.log("PositionFees fundingFeeAmount is between 0 and 1e6"); 727 | | } 728 | | if (fundingFeeAmount > 1e6 && fundingFeeAmount <= 1e12) { 729 | | fl.log("PositionFees fundingFeeAmount is between 1e6 and 1e12"); 730 | | } 731 | | if (fundingFeeAmount > 1e12 && fundingFeeAmount <= 1e18) { 732 | | fl.log("PositionFees fundingFeeAmount is between 1e12 and 1e18"); 733 | | } 734 | | if (fundingFeeAmount > 1e18 && fundingFeeAmount <= 1e24) { 735 | | fl.log("PositionFees fundingFeeAmount is between 1e18 and 1e24"); 736 | | } 737 | | if (fundingFeeAmount > 1e24) { 738 | | fl.log("PositionFees fundingFeeAmount is greater than 1e24"); 739 | | } 740 | | } 741 | | 742 | | function _logPositionFeesClaimableLongTokenAmountCoverage_decreasePosition( 743 | | uint256 claimableLongTokenAmount 744 | | ) internal { 745 | | if (claimableLongTokenAmount == 0) { 746 | | fl.log("PositionFees claimableLongTokenAmount is 0"); 747 | | } 748 | | if (claimableLongTokenAmount > 0 && claimableLongTokenAmount <= 1e6) { 749 | | fl.log( 750 | | "PositionFees claimableLongTokenAmount is between 0 and 1e6" 751 | | ); 752 | | } 753 | | if ( 754 | | claimableLongTokenAmount > 1e6 && claimableLongTokenAmount <= 1e12 755 | | ) { 756 | | fl.log( 757 | | "PositionFees claimableLongTokenAmount is between 1e6 and 1e12" 758 | | ); 759 | | } 760 | | if ( 761 | | claimableLongTokenAmount > 1e12 && claimableLongTokenAmount <= 1e18 762 | | ) { 763 | | fl.log( 764 | | "PositionFees claimableLongTokenAmount is between 1e12 and 1e18" 765 | | ); 766 | | } 767 | | if ( 768 | | claimableLongTokenAmount > 1e18 && claimableLongTokenAmount <= 1e24 769 | | ) { 770 | | fl.log( 771 | | "PositionFees claimableLongTokenAmount is between 1e18 and 1e24" 772 | | ); 773 | | } 774 | | if (claimableLongTokenAmount > 1e24) { 775 | | fl.log( 776 | | "PositionFees claimableLongTokenAmount is greater than 1e24" 777 | | ); 778 | | } 779 | | } 780 | | 781 | | function _logPositionFeesClaimableShortTokenAmountCoverage_decreasePosition( 782 | | uint256 claimableShortTokenAmount 783 | | ) internal { 784 | | if (claimableShortTokenAmount == 0) { 785 | | fl.log("PositionFees claimableShortTokenAmount is 0"); 786 | | } 787 | | if (claimableShortTokenAmount > 0 && claimableShortTokenAmount <= 1e6) { 788 | | fl.log( 789 | | "PositionFees claimableShortTokenAmount is between 0 and 1e6" 790 | | ); 791 | | } 792 | | if ( 793 | | claimableShortTokenAmount > 1e6 && claimableShortTokenAmount <= 1e12 794 | | ) { 795 | | fl.log( 796 | | "PositionFees claimableShortTokenAmount is between 1e6 and 1e12" 797 | | ); 798 | | } 799 | | if ( 800 | | claimableShortTokenAmount > 1e12 && 801 | | claimableShortTokenAmount <= 1e18 802 | | ) { 803 | | fl.log( 804 | | "PositionFees claimableShortTokenAmount is between 1e12 and 1e18" 805 | | ); 806 | | } 807 | | if ( 808 | | claimableShortTokenAmount > 1e18 && 809 | | claimableShortTokenAmount <= 1e24 810 | | ) { 811 | | fl.log( 812 | | "PositionFees claimableShortTokenAmount is between 1e18 and 1e24" 813 | | ); 814 | | } 815 | | if (claimableShortTokenAmount > 1e24) { 816 | | fl.log( 817 | | "PositionFees claimableShortTokenAmount is greater than 1e24" 818 | | ); 819 | | } 820 | | } 821 | | 822 | | function _logPositionFeesLatestFundingFeeAmountPerSizeCoverage_decreasePosition( 823 | | uint256 latestFundingFeeAmountPerSize 824 | | ) internal { 825 | | if (latestFundingFeeAmountPerSize == 0) { 826 | | fl.log("PositionFees latestFundingFeeAmountPerSize is 0"); 827 | | } 828 | | if ( 829 | | latestFundingFeeAmountPerSize > 0 && 830 | | latestFundingFeeAmountPerSize <= 1e6 831 | | ) { 832 | | fl.log( 833 | | "PositionFees latestFundingFeeAmountPerSize is between 0 and 1e6" 834 | | ); 835 | | } 836 | | if ( 837 | | latestFundingFeeAmountPerSize > 1e6 && 838 | | latestFundingFeeAmountPerSize <= 1e12 839 | | ) { 840 | | fl.log( 841 | | "PositionFees latestFundingFeeAmountPerSize is between 1e6 and 1e12" 842 | | ); 843 | | } 844 | | if ( 845 | | latestFundingFeeAmountPerSize > 1e12 && 846 | | latestFundingFeeAmountPerSize <= 1e18 847 | | ) { 848 | | fl.log( 849 | | "PositionFees latestFundingFeeAmountPerSize is between 1e12 and 1e18" 850 | | ); 851 | | } 852 | | if ( 853 | | latestFundingFeeAmountPerSize > 1e18 && 854 | | latestFundingFeeAmountPerSize <= 1e24 855 | | ) { 856 | | fl.log( 857 | | "PositionFees latestFundingFeeAmountPerSize is between 1e18 and 1e24" 858 | | ); 859 | | } 860 | | if (latestFundingFeeAmountPerSize > 1e24) { 861 | | fl.log( 862 | | "PositionFees latestFundingFeeAmountPerSize is greater than 1e24" 863 | | ); 864 | | } 865 | | } 866 | | 867 | | function _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 868 | | uint256 latestLongTokenClaimableFundingAmountPerSize 869 | | ) internal { 870 | | if (latestLongTokenClaimableFundingAmountPerSize == 0) { 871 | | fl.log( 872 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is 0" 873 | | ); 874 | | } 875 | | if ( 876 | | latestLongTokenClaimableFundingAmountPerSize > 0 && 877 | | latestLongTokenClaimableFundingAmountPerSize <= 1e6 878 | | ) { 879 | | fl.log( 880 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 0 and 1e6" 881 | | ); 882 | | } 883 | | if ( 884 | | latestLongTokenClaimableFundingAmountPerSize > 1e6 && 885 | | latestLongTokenClaimableFundingAmountPerSize <= 1e12 886 | | ) { 887 | | fl.log( 888 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 889 | | ); 890 | | } 891 | | if ( 892 | | latestLongTokenClaimableFundingAmountPerSize > 1e12 && 893 | | latestLongTokenClaimableFundingAmountPerSize <= 1e18 894 | | ) { 895 | | fl.log( 896 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 897 | | ); 898 | | } 899 | | if ( 900 | | latestLongTokenClaimableFundingAmountPerSize > 1e18 && 901 | | latestLongTokenClaimableFundingAmountPerSize <= 1e24 902 | | ) { 903 | | fl.log( 904 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 905 | | ); 906 | | } 907 | | if (latestLongTokenClaimableFundingAmountPerSize > 1e24) { 908 | | fl.log( 909 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is greater than 1e24" 910 | | ); 911 | | } 912 | | } 913 | | 914 | | function _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage_decreasePosition( 915 | | uint256 latestShortTokenClaimableFundingAmountPerSize 916 | | ) internal { 917 | | if (latestShortTokenClaimableFundingAmountPerSize == 0) { 918 | | fl.log( 919 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is 0" 920 | | ); 921 | | } 922 | | if ( 923 | | latestShortTokenClaimableFundingAmountPerSize > 0 && 924 | | latestShortTokenClaimableFundingAmountPerSize <= 1e6 925 | | ) { 926 | | fl.log( 927 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 0 and 1e6" 928 | | ); 929 | | } 930 | | if ( 931 | | latestShortTokenClaimableFundingAmountPerSize > 1e6 && 932 | | latestShortTokenClaimableFundingAmountPerSize <= 1e12 933 | | ) { 934 | | fl.log( 935 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 936 | | ); 937 | | } 938 | | if ( 939 | | latestShortTokenClaimableFundingAmountPerSize > 1e12 && 940 | | latestShortTokenClaimableFundingAmountPerSize <= 1e18 941 | | ) { 942 | | fl.log( 943 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 944 | | ); 945 | | } 946 | | if ( 947 | | latestShortTokenClaimableFundingAmountPerSize > 1e18 && 948 | | latestShortTokenClaimableFundingAmountPerSize <= 1e24 949 | | ) { 950 | | fl.log( 951 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 952 | | ); 953 | | } 954 | | if (latestShortTokenClaimableFundingAmountPerSize > 1e24) { 955 | | fl.log( 956 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is greater than 1e24" 957 | | ); 958 | | } 959 | | } 960 | | 961 | | function _logPositionFeesBorrowingFeeUsdCoverage_decreasePosition( 962 | | uint256 borrowingFeeUsd 963 | | ) internal { 964 | | if (borrowingFeeUsd == 0) { 965 | | fl.log("PositionFees borrowingFeeUsd is 0"); 966 | | } 967 | | if (borrowingFeeUsd > 0 && borrowingFeeUsd <= 1e6) { 968 | | fl.log("PositionFees borrowingFeeUsd is between 0 and 1e6"); 969 | | } 970 | | if (borrowingFeeUsd > 1e6 && borrowingFeeUsd <= 1e12) { 971 | | fl.log("PositionFees borrowingFeeUsd is between 1e6 and 1e12"); 972 | | } 973 | | if (borrowingFeeUsd > 1e12 && borrowingFeeUsd <= 1e18) { 974 | | fl.log("PositionFees borrowingFeeUsd is between 1e12 and 1e18"); 975 | | } 976 | | if (borrowingFeeUsd > 1e18 && borrowingFeeUsd <= 1e24) { 977 | | fl.log("PositionFees borrowingFeeUsd is between 1e18 and 1e24"); 978 | | } 979 | | if (borrowingFeeUsd > 1e24) { 980 | | fl.log("PositionFees borrowingFeeUsd is greater than 1e24"); 981 | | } 982 | | } 983 | | 984 | | function _logPositionFeesBorrowingFeeAmountCoverage_decreasePosition( 985 | | uint256 borrowingFeeAmount 986 | | ) internal { 987 | | if (borrowingFeeAmount == 0) { 988 | | fl.log("PositionFees borrowingFeeAmount is 0"); 989 | | } 990 | | if (borrowingFeeAmount > 0 && borrowingFeeAmount <= 1e6) { 991 | | fl.log("PositionFees borrowingFeeAmount is between 0 and 1e6"); 992 | | } 993 | | if (borrowingFeeAmount > 1e6 && borrowingFeeAmount <= 1e12) { 994 | | fl.log("PositionFees borrowingFeeAmount is between 1e6 and 1e12"); 995 | | } 996 | | if (borrowingFeeAmount > 1e12 && borrowingFeeAmount <= 1e18) { 997 | | fl.log("PositionFees borrowingFeeAmount is between 1e12 and 1e18"); 998 | | } 999 | | if (borrowingFeeAmount > 1e18 && borrowingFeeAmount <= 1e24) { 1000 | | fl.log("PositionFees borrowingFeeAmount is between 1e18 and 1e24"); 1001 | | } 1002 | | if (borrowingFeeAmount > 1e24) { 1003 | | fl.log("PositionFees borrowingFeeAmount is greater than 1e24"); 1004 | | } 1005 | | } 1006 | | 1007 | | function _logPositionFeesBorrowingFeeReceiverFactorCoverage_decreasePosition( 1008 | | uint256 borrowingFeeReceiverFactor 1009 | | ) internal { 1010 | | if (borrowingFeeReceiverFactor == 0) { 1011 | | fl.log("PositionFees borrowingFeeReceiverFactor is 0"); 1012 | | } 1013 | | if ( 1014 | | borrowingFeeReceiverFactor > 0 && borrowingFeeReceiverFactor <= 1e6 1015 | | ) { 1016 | | fl.log( 1017 | | "PositionFees borrowingFeeReceiverFactor is between 0 and 1e6" 1018 | | ); 1019 | | } 1020 | | if ( 1021 | | borrowingFeeReceiverFactor > 1e6 && 1022 | | borrowingFeeReceiverFactor <= 1e12 1023 | | ) { 1024 | | fl.log( 1025 | | "PositionFees borrowingFeeReceiverFactor is between 1e6 and 1e12" 1026 | | ); 1027 | | } 1028 | | if ( 1029 | | borrowingFeeReceiverFactor > 1e12 && 1030 | | borrowingFeeReceiverFactor <= 1e18 1031 | | ) { 1032 | | fl.log( 1033 | | "PositionFees borrowingFeeReceiverFactor is between 1e12 and 1e18" 1034 | | ); 1035 | | } 1036 | | if ( 1037 | | borrowingFeeReceiverFactor > 1e18 && 1038 | | borrowingFeeReceiverFactor <= 1e24 1039 | | ) { 1040 | | fl.log( 1041 | | "PositionFees borrowingFeeReceiverFactor is between 1e18 and 1e24" 1042 | | ); 1043 | | } 1044 | | if (borrowingFeeReceiverFactor > 1e24) { 1045 | | fl.log( 1046 | | "PositionFees borrowingFeeReceiverFactor is greater than 1e24" 1047 | | ); 1048 | | } 1049 | | } 1050 | | 1051 | | function _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage_decreasePosition( 1052 | | uint256 borrowingFeeAmountForFeeReceiver 1053 | | ) internal { 1054 | | if (borrowingFeeAmountForFeeReceiver == 0) { 1055 | | fl.log("PositionFees borrowingFeeAmountForFeeReceiver is 0"); 1056 | | } 1057 | | if ( 1058 | | borrowingFeeAmountForFeeReceiver > 0 && 1059 | | borrowingFeeAmountForFeeReceiver <= 1e6 1060 | | ) { 1061 | | fl.log( 1062 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 0 and 1e6" 1063 | | ); 1064 | | } 1065 | | if ( 1066 | | borrowingFeeAmountForFeeReceiver > 1e6 && 1067 | | borrowingFeeAmountForFeeReceiver <= 1e12 1068 | | ) { 1069 | | fl.log( 1070 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e6 and 1e12" 1071 | | ); 1072 | | } 1073 | | if ( 1074 | | borrowingFeeAmountForFeeReceiver > 1e12 && 1075 | | borrowingFeeAmountForFeeReceiver <= 1e18 1076 | | ) { 1077 | | fl.log( 1078 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e12 and 1e18" 1079 | | ); 1080 | | } 1081 | | if ( 1082 | | borrowingFeeAmountForFeeReceiver > 1e18 && 1083 | | borrowingFeeAmountForFeeReceiver <= 1e24 1084 | | ) { 1085 | | fl.log( 1086 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e18 and 1e24" 1087 | | ); 1088 | | } 1089 | | if (borrowingFeeAmountForFeeReceiver > 1e24) { 1090 | | fl.log( 1091 | | "PositionFees borrowingFeeAmountForFeeReceiver is greater than 1e24" 1092 | | ); 1093 | | } 1094 | | } 1095 | | 1096 | | function _logPositionFeesUiFeeReceiverCoverage_decreasePosition( 1097 | | address uiFeeReceiver 1098 | | ) internal { 1099 | | if (uiFeeReceiver == address(0)) { 1100 | | fl.log("PositionFees uiFeeReceiver is address(0)"); 1101 | | } else { 1102 | | fl.log("PositionFees uiFeeReceiver is non-zero address"); 1103 | | } 1104 | | } 1105 | | 1106 | | function _logPositionFeesUiFeeReceiverFactorCoverage_decreasePosition( 1107 | | uint256 uiFeeReceiverFactor 1108 | | ) internal { 1109 | | if (uiFeeReceiverFactor == 0) { 1110 | | fl.log("PositionFees uiFeeReceiverFactor is 0"); 1111 | | } 1112 | | if (uiFeeReceiverFactor > 0 && uiFeeReceiverFactor <= 1e6) { 1113 | | fl.log("PositionFees uiFeeReceiverFactor is between 0 and 1e6"); 1114 | | } 1115 | | if (uiFeeReceiverFactor > 1e6 && uiFeeReceiverFactor <= 1e12) { 1116 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e6 and 1e12"); 1117 | | } 1118 | | if (uiFeeReceiverFactor > 1e12 && uiFeeReceiverFactor <= 1e18) { 1119 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e12 and 1e18"); 1120 | | } 1121 | | if (uiFeeReceiverFactor > 1e18 && uiFeeReceiverFactor <= 1e24) { 1122 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e18 and 1e24"); 1123 | | } 1124 | | if (uiFeeReceiverFactor > 1e24) { 1125 | | fl.log("PositionFees uiFeeReceiverFactor is greater than 1e24"); 1126 | | } 1127 | | } 1128 | | 1129 | | function _logPositionFeesUiFeeAmountCoverage_decreasePosition( 1130 | | uint256 uiFeeAmount 1131 | | ) internal { 1132 | | if (uiFeeAmount == 0) { 1133 | | fl.log("PositionFees uiFeeAmount is 0"); 1134 | | } 1135 | | if (uiFeeAmount > 0 && uiFeeAmount <= 1e6) { 1136 | | fl.log("PositionFees uiFeeAmount is between 0 and 1e6"); 1137 | | } 1138 | | if (uiFeeAmount > 1e6 && uiFeeAmount <= 1e12) { 1139 | | fl.log("PositionFees uiFeeAmount is between 1e6 and 1e12"); 1140 | | } 1141 | | if (uiFeeAmount > 1e12 && uiFeeAmount <= 1e18) { 1142 | | fl.log("PositionFees uiFeeAmount is between 1e12 and 1e18"); 1143 | | } 1144 | | if (uiFeeAmount > 1e18 && uiFeeAmount <= 1e24) { 1145 | | fl.log("PositionFees uiFeeAmount is between 1e18 and 1e24"); 1146 | | } 1147 | | if (uiFeeAmount > 1e24) { 1148 | | fl.log("PositionFees uiFeeAmount is greater than 1e24"); 1149 | | } 1150 | | } 1151 | | 1152 | | function _logPositionFeesCollateralTokenPriceCoverage_decreasePosition( 1153 | | uint256 collateralTokenPrice 1154 | | ) internal { 1155 | | if (collateralTokenPrice == 0) { 1156 | | fl.log("PositionFees collateralTokenPrice is 0"); 1157 | | } 1158 | | if (collateralTokenPrice > 0 && collateralTokenPrice <= 1e6) { 1159 | | fl.log("PositionFees collateralTokenPrice is between 0 and 1e6"); 1160 | | } 1161 | | if (collateralTokenPrice > 1e6 && collateralTokenPrice <= 1e12) { 1162 | | fl.log("PositionFees collateralTokenPrice is between 1e6 and 1e12"); 1163 | | } 1164 | | if (collateralTokenPrice > 1e12 && collateralTokenPrice <= 1e18) { 1165 | | fl.log( 1166 | | "PositionFees collateralTokenPrice is between 1e12 and 1e18" 1167 | | ); 1168 | | } 1169 | | if (collateralTokenPrice > 1e18 && collateralTokenPrice <= 1e24) { 1170 | | fl.log( 1171 | | "PositionFees collateralTokenPrice is between 1e18 and 1e24" 1172 | | ); 1173 | | } 1174 | | if (collateralTokenPrice > 1e24) { 1175 | | fl.log("PositionFees collateralTokenPrice is greater than 1e24"); 1176 | | } 1177 | | } 1178 | | 1179 | | function _logPositionFeesPositionFeeFactorCoverage_decreasePosition( 1180 | | uint256 positionFeeFactor 1181 | | ) internal { 1182 | | if (positionFeeFactor == 0) { 1183 | | fl.log("PositionFees positionFeeFactor is 0"); 1184 | | } 1185 | | if (positionFeeFactor > 0 && positionFeeFactor <= 1e6) { 1186 | | fl.log("PositionFees positionFeeFactor is between 0 and 1e6"); 1187 | | } 1188 | | if (positionFeeFactor > 1e6 && positionFeeFactor <= 1e12) { 1189 | | fl.log("PositionFees positionFeeFactor is between 1e6 and 1e12"); 1190 | | } 1191 | | if (positionFeeFactor > 1e12 && positionFeeFactor <= 1e18) { 1192 | | fl.log("PositionFees positionFeeFactor is between 1e12 and 1e18"); 1193 | | } 1194 | | if (positionFeeFactor > 1e18 && positionFeeFactor <= 1e24) { 1195 | | fl.log("PositionFees positionFeeFactor is between 1e18 and 1e24"); 1196 | | } 1197 | | if (positionFeeFactor > 1e24) { 1198 | | fl.log("PositionFees positionFeeFactor is greater than 1e24"); 1199 | | } 1200 | | } 1201 | | function _logPositionFeesProtocolFeeAmountCoverage_decreasePosition( 1202 | | uint256 protocolFeeAmount 1203 | | ) internal { 1204 | | if (protocolFeeAmount == 0) { 1205 | | fl.log("PositionFees protocolFeeAmount is 0"); 1206 | | } 1207 | | if (protocolFeeAmount > 0 && protocolFeeAmount <= 1e6) { 1208 | | fl.log("PositionFees protocolFeeAmount is between 0 and 1e6"); 1209 | | } 1210 | | if (protocolFeeAmount > 1e6 && protocolFeeAmount <= 1e12) { 1211 | | fl.log("PositionFees protocolFeeAmount is between 1e6 and 1e12"); 1212 | | } 1213 | | if (protocolFeeAmount > 1e12 && protocolFeeAmount <= 1e18) { 1214 | | fl.log("PositionFees protocolFeeAmount is between 1e12 and 1e18"); 1215 | | } 1216 | | if (protocolFeeAmount > 1e18 && protocolFeeAmount <= 1e24) { 1217 | | fl.log("PositionFees protocolFeeAmount is between 1e18 and 1e24"); 1218 | | } 1219 | | if (protocolFeeAmount > 1e24) { 1220 | | fl.log("PositionFees protocolFeeAmount is greater than 1e24"); 1221 | | } 1222 | | } 1223 | | function _logPositionFeesPositionFeeReceiverFactorCoverage_decreasePosition( 1224 | | uint256 positionFeeReceiverFactor 1225 | | ) internal { 1226 | | if (positionFeeReceiverFactor == 0) { 1227 | | fl.log("PositionFees positionFeeReceiverFactor is 0"); 1228 | | } 1229 | | 1230 | | if (positionFeeReceiverFactor > 0 && positionFeeReceiverFactor <= 1e6) { 1231 | | fl.log( 1232 | | "PositionFees positionFeeReceiverFactor is between 0 and 1e6" 1233 | | ); 1234 | | } 1235 | | 1236 | | if ( 1237 | | positionFeeReceiverFactor > 1e6 && positionFeeReceiverFactor <= 1e12 1238 | | ) { 1239 | | fl.log( 1240 | | "PositionFees positionFeeReceiverFactor is between 1e6 and 1e12" 1241 | | ); 1242 | | } 1243 | | 1244 | | if ( 1245 | | positionFeeReceiverFactor > 1e12 && 1246 | | positionFeeReceiverFactor <= 1e18 1247 | | ) { 1248 | | fl.log( 1249 | | "PositionFees positionFeeReceiverFactor is between 1e12 and 1e18" 1250 | | ); 1251 | | } 1252 | | 1253 | | if ( 1254 | | positionFeeReceiverFactor > 1e18 && 1255 | | positionFeeReceiverFactor <= 1e24 1256 | | ) { 1257 | | fl.log( 1258 | | "PositionFees positionFeeReceiverFactor is between 1e18 and 1e24" 1259 | | ); 1260 | | } 1261 | | 1262 | | if (positionFeeReceiverFactor > 1e24) { 1263 | | fl.log( 1264 | | "PositionFees positionFeeReceiverFactor is greater than 1e24" 1265 | | ); 1266 | | } 1267 | | } 1268 | | 1269 | | function _logPositionFeesFeeReceiverAmountCoverage_decreasePosition( 1270 | | uint256 feeReceiverAmount 1271 | | ) internal { 1272 | | if (feeReceiverAmount == 0) { 1273 | | fl.log("PositionFees feeReceiverAmount is 0"); 1274 | | } 1275 | | if (feeReceiverAmount > 0 && feeReceiverAmount <= 1e6) { 1276 | | fl.log("PositionFees feeReceiverAmount is between 0 and 1e6"); 1277 | | } 1278 | | if (feeReceiverAmount > 1e6 && feeReceiverAmount <= 1e12) { 1279 | | fl.log("PositionFees feeReceiverAmount is between 1e6 and 1e12"); 1280 | | } 1281 | | if (feeReceiverAmount > 1e12 && feeReceiverAmount <= 1e18) { 1282 | | fl.log("PositionFees feeReceiverAmount is between 1e12 and 1e18"); 1283 | | } 1284 | | if (feeReceiverAmount > 1e18 && feeReceiverAmount <= 1e24) { 1285 | | fl.log("PositionFees feeReceiverAmount is between 1e18 and 1e24"); 1286 | | } 1287 | | if (feeReceiverAmount > 1e24) { 1288 | | fl.log("PositionFees feeReceiverAmount is greater than 1e24"); 1289 | | } 1290 | | } 1291 | | 1292 | | function _logPositionFeesFeeAmountForPoolCoverage_decreasePosition( 1293 | | uint256 feeAmountForPool 1294 | | ) internal { 1295 | | if (feeAmountForPool == 0) { 1296 | | fl.log("PositionFees feeAmountForPool is 0"); 1297 | | } 1298 | | if (feeAmountForPool > 0 && feeAmountForPool <= 1e6) { 1299 | | fl.log("PositionFees feeAmountForPool is between 0 and 1e6"); 1300 | | } 1301 | | if (feeAmountForPool > 1e6 && feeAmountForPool <= 1e12) { 1302 | | fl.log("PositionFees feeAmountForPool is between 1e6 and 1e12"); 1303 | | } 1304 | | if (feeAmountForPool > 1e12 && feeAmountForPool <= 1e18) { 1305 | | fl.log("PositionFees feeAmountForPool is between 1e12 and 1e18"); 1306 | | } 1307 | | if (feeAmountForPool > 1e18 && feeAmountForPool <= 1e24) { 1308 | | fl.log("PositionFees feeAmountForPool is between 1e18 and 1e24"); 1309 | | } 1310 | | if (feeAmountForPool > 1e24) { 1311 | | fl.log("PositionFees feeAmountForPool is greater than 1e24"); 1312 | | } 1313 | | } 1314 | | 1315 | | function _logPositionFeesPositionFeeAmountForPoolCoverage_decreasePosition( 1316 | | uint256 positionFeeAmountForPool 1317 | | ) internal { 1318 | | if (positionFeeAmountForPool == 0) { 1319 | | fl.log("PositionFees positionFeeAmountForPool is 0"); 1320 | | } 1321 | | if (positionFeeAmountForPool > 0 && positionFeeAmountForPool <= 1e6) { 1322 | | fl.log( 1323 | | "PositionFees positionFeeAmountForPool is between 0 and 1e6" 1324 | | ); 1325 | | } 1326 | | if ( 1327 | | positionFeeAmountForPool > 1e6 && positionFeeAmountForPool <= 1e12 1328 | | ) { 1329 | | fl.log( 1330 | | "PositionFees positionFeeAmountForPool is between 1e6 and 1e12" 1331 | | ); 1332 | | } 1333 | | if ( 1334 | | positionFeeAmountForPool > 1e12 && positionFeeAmountForPool <= 1e18 1335 | | ) { 1336 | | fl.log( 1337 | | "PositionFees positionFeeAmountForPool is between 1e12 and 1e18" 1338 | | ); 1339 | | } 1340 | | if ( 1341 | | positionFeeAmountForPool > 1e18 && positionFeeAmountForPool <= 1e24 1342 | | ) { 1343 | | fl.log( 1344 | | "PositionFees positionFeeAmountForPool is between 1e18 and 1e24" 1345 | | ); 1346 | | } 1347 | | if (positionFeeAmountForPool > 1e24) { 1348 | | fl.log( 1349 | | "PositionFees positionFeeAmountForPool is greater than 1e24" 1350 | | ); 1351 | | } 1352 | | } 1353 | | 1354 | | function _logPositionFeesPositionFeeAmountCoverage_decreasePosition( 1355 | | uint256 positionFeeAmount 1356 | | ) internal { 1357 | | if (positionFeeAmount == 0) { 1358 | | fl.log("PositionFees positionFeeAmount is 0"); 1359 | | } 1360 | | if (positionFeeAmount > 0 && positionFeeAmount <= 1e6) { 1361 | | fl.log("PositionFees positionFeeAmount is between 0 and 1e6"); 1362 | | } 1363 | | if (positionFeeAmount > 1e6 && positionFeeAmount <= 1e12) { 1364 | | fl.log("PositionFees positionFeeAmount is between 1e6 and 1e12"); 1365 | | } 1366 | | if (positionFeeAmount > 1e12 && positionFeeAmount <= 1e18) { 1367 | | fl.log("PositionFees positionFeeAmount is between 1e12 and 1e18"); 1368 | | } 1369 | | if (positionFeeAmount > 1e18 && positionFeeAmount <= 1e24) { 1370 | | fl.log("PositionFees positionFeeAmount is between 1e18 and 1e24"); 1371 | | } 1372 | | if (positionFeeAmount > 1e24) { 1373 | | fl.log("PositionFees positionFeeAmount is greater than 1e24"); 1374 | | } 1375 | | } 1376 | | 1377 | | function _logPositionFeesTotalCostAmountExcludingFundingCoverage_decreasePosition( 1378 | | uint256 totalCostAmountExcludingFunding 1379 | | ) internal { 1380 | | if (totalCostAmountExcludingFunding == 0) { 1381 | | fl.log("PositionFees totalCostAmountExcludingFunding is 0"); 1382 | | } 1383 | | if ( 1384 | | totalCostAmountExcludingFunding > 0 && 1385 | | totalCostAmountExcludingFunding <= 1e6 1386 | | ) { 1387 | | fl.log( 1388 | | "PositionFees totalCostAmountExcludingFunding is between 0 and 1e6" 1389 | | ); 1390 | | } 1391 | | if ( 1392 | | totalCostAmountExcludingFunding > 1e6 && 1393 | | totalCostAmountExcludingFunding <= 1e12 1394 | | ) { 1395 | | fl.log( 1396 | | "PositionFees totalCostAmountExcludingFunding is between 1e6 and 1e12" 1397 | | ); 1398 | | } 1399 | | if ( 1400 | | totalCostAmountExcludingFunding > 1e12 && 1401 | | totalCostAmountExcludingFunding <= 1e18 1402 | | ) { 1403 | | fl.log( 1404 | | "PositionFees totalCostAmountExcludingFunding is between 1e12 and 1e18" 1405 | | ); 1406 | | } 1407 | | if ( 1408 | | totalCostAmountExcludingFunding > 1e18 && 1409 | | totalCostAmountExcludingFunding <= 1e24 1410 | | ) { 1411 | | fl.log( 1412 | | "PositionFees totalCostAmountExcludingFunding is between 1e18 and 1e24" 1413 | | ); 1414 | | } 1415 | | if (totalCostAmountExcludingFunding > 1e24) { 1416 | | fl.log( 1417 | | "PositionFees totalCostAmountExcludingFunding is greater than 1e24" 1418 | | ); 1419 | | } 1420 | | } 1421 | | 1422 | | function _logPositionFeesTotalCostAmountCoverage_decreasePosition( 1423 | | uint256 totalCostAmount 1424 | | ) internal { 1425 | | if (totalCostAmount == 0) { 1426 | | fl.log("PositionFees totalCostAmount is 0"); 1427 | | } 1428 | | if (totalCostAmount > 0 && totalCostAmount <= 1e6) { 1429 | | fl.log("PositionFees totalCostAmount is between 0 and 1e6"); 1430 | | } 1431 | | if (totalCostAmount > 1e6 && totalCostAmount <= 1e12) { 1432 | | fl.log("PositionFees totalCostAmount is between 1e6 and 1e12"); 1433 | | } 1434 | | if (totalCostAmount > 1e12 && totalCostAmount <= 1e18) { 1435 | | fl.log("PositionFees totalCostAmount is between 1e12 and 1e18"); 1436 | | } 1437 | | if (totalCostAmount > 1e18 && totalCostAmount <= 1e24) { 1438 | | fl.log("PositionFees totalCostAmount is between 1e18 and 1e24"); 1439 | | } 1440 | | if (totalCostAmount > 1e24) { 1441 | | fl.log("PositionFees totalCostAmount is greater than 1e24"); 1442 | | } 1443 | | } 1444 | | 1445 | | function _logExecutionPriceResultPriceImpactUsdCoverage_decreasePosition( 1446 | | int256 priceImpactUsd 1447 | | ) internal { 1448 | | if (priceImpactUsd == 0) { 1449 | | fl.log("ExecutionPriceResult priceImpactUsd is 0"); 1450 | | } 1451 | | if (priceImpactUsd > 0 && priceImpactUsd <= 1e6) { 1452 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and 1e6"); 1453 | | } 1454 | | if (priceImpactUsd > 1e6 && priceImpactUsd <= 1e12) { 1455 | | fl.log( 1456 | | "ExecutionPriceResult priceImpactUsd is between 1e6 and 1e12" 1457 | | ); 1458 | | } 1459 | | if (priceImpactUsd > 1e12 && priceImpactUsd <= 1e18) { 1460 | | fl.log( 1461 | | "ExecutionPriceResult priceImpactUsd is between 1e12 and 1e18" 1462 | | ); 1463 | | } 1464 | | if (priceImpactUsd > 1e18 && priceImpactUsd <= 1e24) { 1465 | | fl.log( 1466 | | "ExecutionPriceResult priceImpactUsd is between 1e18 and 1e24" 1467 | | ); 1468 | | } 1469 | | if (priceImpactUsd > 1e24) { 1470 | | fl.log("ExecutionPriceResult priceImpactUsd is greater than 1e24"); 1471 | | } 1472 | | if (priceImpactUsd < 0 && priceImpactUsd >= -1e6) { 1473 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and -1e6"); 1474 | | } 1475 | | if (priceImpactUsd < -1e6 && priceImpactUsd >= -1e12) { 1476 | | fl.log( 1477 | | "ExecutionPriceResult priceImpactUsd is between -1e6 and -1e12" 1478 | | ); 1479 | | } 1480 | | if (priceImpactUsd < -1e12 && priceImpactUsd >= -1e18) { 1481 | | fl.log( 1482 | | "ExecutionPriceResult priceImpactUsd is between -1e12 and -1e18" 1483 | | ); 1484 | | } 1485 | | if (priceImpactUsd < -1e18 && priceImpactUsd >= -1e24) { 1486 | | fl.log( 1487 | | "ExecutionPriceResult priceImpactUsd is between -1e18 and -1e24" 1488 | | ); 1489 | | } 1490 | | if (priceImpactUsd < -1e24) { 1491 | | fl.log("ExecutionPriceResult priceImpactUsd is less than -1e24"); 1492 | | } 1493 | | } 1494 | | function _logExecutionPriceResultPriceImpactDiffUsdCoverage_decreasePosition( 1495 | | uint256 priceImpactDiffUsd 1496 | | ) internal { 1497 | | if (priceImpactDiffUsd == 0) { 1498 | | fl.log("ExecutionPriceResult priceImpactDiffUsd is 0"); 1499 | | } 1500 | | if (priceImpactDiffUsd > 0 && priceImpactDiffUsd <= 1e6) { 1501 | | fl.log( 1502 | | "ExecutionPriceResult priceImpactDiffUsd is between 0 and 1e6" 1503 | | ); 1504 | | } 1505 | | if (priceImpactDiffUsd > 1e6 && priceImpactDiffUsd <= 1e12) { 1506 | | fl.log( 1507 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e6 and 1e12" 1508 | | ); 1509 | | } 1510 | | if (priceImpactDiffUsd > 1e12 && priceImpactDiffUsd <= 1e18) { 1511 | | fl.log( 1512 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e12 and 1e18" 1513 | | ); 1514 | | } 1515 | | if (priceImpactDiffUsd > 1e18 && priceImpactDiffUsd <= 1e24) { 1516 | | fl.log( 1517 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e18 and 1e24" 1518 | | ); 1519 | | } 1520 | | if (priceImpactDiffUsd > 1e24) { 1521 | | fl.log( 1522 | | "ExecutionPriceResult priceImpactDiffUsd is greater than 1e24" 1523 | | ); 1524 | | } 1525 | | } 1526 | | function _logExecutionPriceResultExecutionPriceCoverage_decreasePosition( 1527 | | uint256 executionPrice 1528 | | ) internal { 1529 | | if (executionPrice == 0) { 1530 | | fl.log("ExecutionPriceResult executionPrice is 0"); 1531 | | } 1532 | | if (executionPrice > 0 && executionPrice <= 1e6) { 1533 | | fl.log("ExecutionPriceResult executionPrice is between 0 and 1e6"); 1534 | | } 1535 | | if (executionPrice > 1e6 && executionPrice <= 1e12) { 1536 | | fl.log( 1537 | | "ExecutionPriceResult executionPrice is between 1e6 and 1e12" 1538 | | ); 1539 | | } 1540 | | if (executionPrice > 1e12 && executionPrice <= 1e18) { 1541 | | fl.log( 1542 | | "ExecutionPriceResult executionPrice is between 1e12 and 1e18" 1543 | | ); 1544 | | } 1545 | | if (executionPrice > 1e18 && executionPrice <= 1e24) { 1546 | | fl.log( 1547 | | "ExecutionPriceResult executionPrice is between 1e18 and 1e24" 1548 | | ); 1549 | | } 1550 | | if (executionPrice > 1e24) { 1551 | | fl.log("ExecutionPriceResult executionPrice is greater than 1e24"); 1552 | | } 1553 | | } 1554 | | function _logPositionInfoBasePnlUsdCoverage_decreasePosition( 1555 | | int256 basePnlUsd 1556 | | ) internal { 1557 | | if (basePnlUsd == 0) { 1558 | | fl.log("PositionInfo basePnlUsd is 0"); 1559 | | } 1560 | | if (basePnlUsd > 0 && basePnlUsd <= 1e6) { 1561 | | fl.log("PositionInfo basePnlUsd is between 0 and 1e6"); 1562 | | } 1563 | | if (basePnlUsd > 1e6 && basePnlUsd <= 1e12) { 1564 | | fl.log("PositionInfo basePnlUsd is between 1e6 and 1e12"); 1565 | | } 1566 | | if (basePnlUsd > 1e12 && basePnlUsd <= 1e18) { 1567 | | fl.log("PositionInfo basePnlUsd is between 1e12 and 1e18"); 1568 | | } 1569 | | if (basePnlUsd > 1e18 && basePnlUsd <= 1e24) { 1570 | | fl.log("PositionInfo basePnlUsd is between 1e18 and 1e24"); 1571 | | } 1572 | | if (basePnlUsd > 1e24) { 1573 | | fl.log("PositionInfo basePnlUsd is greater than 1e24"); 1574 | | } 1575 | | if (basePnlUsd < 0 && basePnlUsd >= -1e6) { 1576 | | fl.log("PositionInfo basePnlUsd is between 0 and -1e6"); 1577 | | } 1578 | | if (basePnlUsd < -1e6 && basePnlUsd >= -1e12) { 1579 | | fl.log("PositionInfo basePnlUsd is between -1e6 and -1e12"); 1580 | | } 1581 | | if (basePnlUsd < -1e12 && basePnlUsd >= -1e18) { 1582 | | fl.log("PositionInfo basePnlUsd is between -1e12 and -1e18"); 1583 | | } 1584 | | if (basePnlUsd < -1e18 && basePnlUsd >= -1e24) { 1585 | | fl.log("PositionInfo basePnlUsd is between -1e18 and -1e24"); 1586 | | } 1587 | | if (basePnlUsd < -1e24) { 1588 | | fl.log("PositionInfo basePnlUsd is less than -1e24"); 1589 | | } 1590 | | } 1591 | | function _logPositionInfoUncappedBasePnlUsdCoverage_decreasePosition( 1592 | | int256 uncappedBasePnlUsd 1593 | | ) internal { 1594 | | if (uncappedBasePnlUsd == 0) { 1595 | | fl.log("PositionInfo uncappedBasePnlUsd is 0"); 1596 | | } 1597 | | if (uncappedBasePnlUsd > 0 && uncappedBasePnlUsd <= 1e6) { 1598 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and 1e6"); 1599 | | } 1600 | | if (uncappedBasePnlUsd > 1e6 && uncappedBasePnlUsd <= 1e12) { 1601 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e6 and 1e12"); 1602 | | } 1603 | | if (uncappedBasePnlUsd > 1e12 && uncappedBasePnlUsd <= 1e18) { 1604 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e12 and 1e18"); 1605 | | } 1606 | | if (uncappedBasePnlUsd > 1e18 && uncappedBasePnlUsd <= 1e24) { 1607 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e18 and 1e24"); 1608 | | } 1609 | | if (uncappedBasePnlUsd > 1e24) { 1610 | | fl.log("PositionInfo uncappedBasePnlUsd is greater than 1e24"); 1611 | | } 1612 | | if (uncappedBasePnlUsd < 0 && uncappedBasePnlUsd >= -1e6) { 1613 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and -1e6"); 1614 | | } 1615 | | if (uncappedBasePnlUsd < -1e6 && uncappedBasePnlUsd >= -1e12) { 1616 | | fl.log("PositionInfo uncappedBasePnlUsd is between -1e6 and -1e12"); 1617 | | } 1618 | | if (uncappedBasePnlUsd < -1e12 && uncappedBasePnlUsd >= -1e18) { 1619 | | fl.log( 1620 | | "PositionInfo uncappedBasePnlUsd is between -1e12 and -1e18" 1621 | | ); 1622 | | } 1623 | | if (uncappedBasePnlUsd < -1e18 && uncappedBasePnlUsd >= -1e24) { 1624 | | fl.log( 1625 | | "PositionInfo uncappedBasePnlUsd is between -1e18 and -1e24" 1626 | | ); 1627 | | } 1628 | | if (uncappedBasePnlUsd < -1e24) { 1629 | | fl.log("PositionInfo uncappedBasePnlUsd is less than -1e24"); 1630 | | } 1631 | | } 1632 | | function _logPositionInfoPnlAfterPriceImpactUsdCoverage_decreasePosition( 1633 | | int256 pnlAfterPriceImpactUsd 1634 | | ) internal { 1635 | | if (pnlAfterPriceImpactUsd == 0) { 1636 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is 0"); 1637 | | } 1638 | | if (pnlAfterPriceImpactUsd > 0 && pnlAfterPriceImpactUsd <= 1e6) { 1639 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and 1e6"); 1640 | | } 1641 | | if (pnlAfterPriceImpactUsd > 1e6 && pnlAfterPriceImpactUsd <= 1e12) { 1642 | | fl.log( 1643 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e6 and 1e12" 1644 | | ); 1645 | | } 1646 | | if (pnlAfterPriceImpactUsd > 1e12 && pnlAfterPriceImpactUsd <= 1e18) { 1647 | | fl.log( 1648 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e12 and 1e18" 1649 | | ); 1650 | | } 1651 | | if (pnlAfterPriceImpactUsd > 1e18 && pnlAfterPriceImpactUsd <= 1e24) { 1652 | | fl.log( 1653 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e18 and 1e24" 1654 | | ); 1655 | | } 1656 | | if (pnlAfterPriceImpactUsd > 1e24) { 1657 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is greater than 1e24"); 1658 | | } 1659 | | if (pnlAfterPriceImpactUsd < 0 && pnlAfterPriceImpactUsd >= -1e6) { 1660 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and -1e6"); 1661 | | } 1662 | | if (pnlAfterPriceImpactUsd < -1e6 && pnlAfterPriceImpactUsd >= -1e12) { 1663 | | fl.log( 1664 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e6 and -1e12" 1665 | | ); 1666 | | } 1667 | | if (pnlAfterPriceImpactUsd < -1e12 && pnlAfterPriceImpactUsd >= -1e18) { 1668 | | fl.log( 1669 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e12 and -1e18" 1670 | | ); 1671 | | } 1672 | | if (pnlAfterPriceImpactUsd < -1e18 && pnlAfterPriceImpactUsd >= -1e24) { 1673 | | fl.log( 1674 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e18 and -1e24" 1675 | | ); 1676 | | } 1677 | | if (pnlAfterPriceImpactUsd < -1e24) { 1678 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is less than -1e24"); 1679 | | } 1680 | | } 1681 | | } 1682 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/DecreasePositionMarketCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract DecreasePositionMarketCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ DECREASE POSITION 10 | | // __^ __( \.__) ) GET MARKET INFO 11 | | // (@)<_____>__(_____)____/ COVERAGE 12 | | 13 | | function _checkDecreaseOrderAndGetMarketInfoCoverage( 14 | | ReaderUtils.MarketInfo memory marketInfo 15 | | ) internal { 16 | | _logMarketInfoMarketTokenCoverage_decreasePosition( 17 | | marketInfo.market.marketToken 18 | | ); 19 | | _logMarketInfoIndexTokenCoverage_decreasePosition( 20 | | marketInfo.market.indexToken 21 | | ); 22 | | _logMarketInfoLongTokenCoverage_decreasePosition( 23 | | marketInfo.market.longToken 24 | | ); 25 | | _logMarketInfoShortTokenCoverage_decreasePosition( 26 | | marketInfo.market.shortToken 27 | | ); 28 | | _logMarketInfoBorrowingFactorPerSecondForLongsCoverage_decreasePosition( 29 | | marketInfo.borrowingFactorPerSecondForLongs 30 | | ); 31 | | _logMarketInfoBorrowingFactorPerSecondForShortsCoverage_decreasePosition( 32 | | marketInfo.borrowingFactorPerSecondForShorts 33 | | ); 34 | | _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage_decreasePosition( 35 | | marketInfo.baseFunding.fundingFeeAmountPerSize.long 36 | | ); 37 | | _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage_decreasePosition( 38 | | marketInfo.baseFunding.fundingFeeAmountPerSize.short 39 | | ); 40 | | _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage_decreasePosition( 41 | | marketInfo.baseFunding.claimableFundingAmountPerSize.long 42 | | ); 43 | | _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage_decreasePosition( 44 | | marketInfo.baseFunding.claimableFundingAmountPerSize.short 45 | | ); 46 | | _logMarketInfoNextFundingLongsPayShortsCoverage_decreasePosition( 47 | | marketInfo.nextFunding.longsPayShorts 48 | | ); 49 | | _logMarketInfoNextFundingFundingFactorPerSecondCoverage_decreasePosition( 50 | | marketInfo.nextFunding.fundingFactorPerSecond 51 | | ); 52 | | _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage_decreasePosition( 53 | | marketInfo.nextFunding.nextSavedFundingFactorPerSecond 54 | | ); 55 | | _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage_decreasePosition( 56 | | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.long 57 | | ); 58 | | _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage_decreasePosition( 59 | | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.short 60 | | ); 61 | | _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition( 62 | | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.long 63 | | ); 64 | | _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition( 65 | | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.short 66 | | ); 67 | | _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage_decreasePosition( 68 | | marketInfo.virtualInventory.virtualPoolAmountForLongToken 69 | | ); 70 | | _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage_decreasePosition( 71 | | marketInfo.virtualInventory.virtualPoolAmountForShortToken 72 | | ); 73 | | _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage_decreasePosition( 74 | | marketInfo.virtualInventory.virtualInventoryForPositions 75 | | ); 76 | | _logMarketInfoIsDisabledCoverage_decreasePosition( 77 | | marketInfo.isDisabled 78 | | ); 79 | | } 80 | | 81 | | function _logMarketInfoMarketTokenCoverage_decreasePosition( 82 | | address marketToken 83 | | ) internal { 84 | | if (marketToken == address(market_0_WETH_USDC)) { 85 | | fl.log("MarketInfo marketToken market_0_WETH_USDC hit"); 86 | | } 87 | | 88 | | if (marketToken == address(market_WBTC_WBTC_USDC)) { 89 | | fl.log("MarketInfo marketToken market_WBTC_WBTC_USDC hit"); 90 | | } 91 | | if (marketToken == address(market_WETH_WETH_USDC)) { 92 | | fl.log("MarketInfo marketToken market_WETH_WETH_USDC hit"); 93 | | } 94 | | if (marketToken == address(market_WETH_WETH_USDT)) { 95 | | fl.log("MarketInfo marketToken market_WETH_WETH_USDT hit"); 96 | | } 97 | | } 98 | | 99 | | function _logMarketInfoIndexTokenCoverage_decreasePosition( 100 | | address indexToken 101 | | ) internal { 102 | | if (indexToken == address(0)) { 103 | | fl.log("MarketInfo indexToken is address(0)"); 104 | | } else { 105 | | fl.log("MarketInfo indexToken is non-zero address"); 106 | | } 107 | | } 108 | | 109 | | function _logMarketInfoLongTokenCoverage_decreasePosition( 110 | | address longToken 111 | | ) internal { 112 | | if (longToken == address(0)) { 113 | | fl.log("MarketInfo longToken is address(0)"); 114 | | } else { 115 | | fl.log("MarketInfo longToken is non-zero address"); 116 | | } 117 | | } 118 | | 119 | | function _logMarketInfoShortTokenCoverage_decreasePosition( 120 | | address shortToken 121 | | ) internal { 122 | | if (shortToken == address(0)) { 123 | | fl.log("MarketInfo shortToken is address(0)"); 124 | | } else { 125 | | fl.log("MarketInfo shortToken is non-zero address"); 126 | | } 127 | | } 128 | | 129 | | function _logMarketInfoBorrowingFactorPerSecondForLongsCoverage_decreasePosition( 130 | | uint256 borrowingFactorPerSecondForLongs 131 | | ) internal { 132 | | if (borrowingFactorPerSecondForLongs == 0) { 133 | | fl.log("MarketInfo borrowingFactorPerSecondForLongs is 0"); 134 | | } 135 | | if ( 136 | | borrowingFactorPerSecondForLongs > 0 && 137 | | borrowingFactorPerSecondForLongs <= 1e6 138 | | ) { 139 | | fl.log( 140 | | "MarketInfo borrowingFactorPerSecondForLongs is between 0 and 1e6" 141 | | ); 142 | | } 143 | | if ( 144 | | borrowingFactorPerSecondForLongs > 1e6 && 145 | | borrowingFactorPerSecondForLongs <= 1e12 146 | | ) { 147 | | fl.log( 148 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e6 and 1e12" 149 | | ); 150 | | } 151 | | if ( 152 | | borrowingFactorPerSecondForLongs > 1e12 && 153 | | borrowingFactorPerSecondForLongs <= 1e18 154 | | ) { 155 | | fl.log( 156 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e12 and 1e18" 157 | | ); 158 | | } 159 | | if ( 160 | | borrowingFactorPerSecondForLongs > 1e18 && 161 | | borrowingFactorPerSecondForLongs <= 1e24 162 | | ) { 163 | | fl.log( 164 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e18 and 1e24" 165 | | ); 166 | | } 167 | | if (borrowingFactorPerSecondForLongs > 1e24) { 168 | | fl.log( 169 | | "MarketInfo borrowingFactorPerSecondForLongs is greater than 1e24" 170 | | ); 171 | | } 172 | | } 173 | | 174 | | function _logMarketInfoBorrowingFactorPerSecondForShortsCoverage_decreasePosition( 175 | | uint256 borrowingFactorPerSecondForShorts 176 | | ) internal { 177 | | if (borrowingFactorPerSecondForShorts == 0) { 178 | | fl.log("MarketInfo borrowingFactorPerSecondForShorts is 0"); 179 | | } 180 | | if ( 181 | | borrowingFactorPerSecondForShorts > 0 && 182 | | borrowingFactorPerSecondForShorts <= 1e6 183 | | ) { 184 | | fl.log( 185 | | "MarketInfo borrowingFactorPerSecondForShorts is between 0 and 1e6" 186 | | ); 187 | | } 188 | | if ( 189 | | borrowingFactorPerSecondForShorts > 1e6 && 190 | | borrowingFactorPerSecondForShorts <= 1e12 191 | | ) { 192 | | fl.log( 193 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e6 and 1e12" 194 | | ); 195 | | } 196 | | if ( 197 | | borrowingFactorPerSecondForShorts > 1e12 && 198 | | borrowingFactorPerSecondForShorts <= 1e18 199 | | ) { 200 | | fl.log( 201 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e12 and 1e18" 202 | | ); 203 | | } 204 | | if ( 205 | | borrowingFactorPerSecondForShorts > 1e18 && 206 | | borrowingFactorPerSecondForShorts <= 1e24 207 | | ) { 208 | | fl.log( 209 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e18 and 1e24" 210 | | ); 211 | | } 212 | | if (borrowingFactorPerSecondForShorts > 1e24) { 213 | | fl.log( 214 | | "MarketInfo borrowingFactorPerSecondForShorts is greater than 1e24" 215 | | ); 216 | | } 217 | | } 218 | | 219 | | function _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage_decreasePosition( 220 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSize 221 | | ) internal { 222 | | if ( 223 | | longFundingFeeAmountPerSize.longToken == 0 && 224 | | longFundingFeeAmountPerSize.shortToken == 0 225 | | ) { 226 | | fl.log( 227 | | "MarketInfo baseFunding longFundingFeeAmountPerSize is 0 for both longToken and shortToken" 228 | | ); 229 | | } 230 | | if ( 231 | | longFundingFeeAmountPerSize.longToken > 0 && 232 | | longFundingFeeAmountPerSize.longToken <= 1e6 233 | | ) { 234 | | fl.log( 235 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 0 and 1e6" 236 | | ); 237 | | } 238 | | if ( 239 | | longFundingFeeAmountPerSize.longToken > 1e6 && 240 | | longFundingFeeAmountPerSize.longToken <= 1e12 241 | | ) { 242 | | fl.log( 243 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e6 and 1e12" 244 | | ); 245 | | } 246 | | if ( 247 | | longFundingFeeAmountPerSize.longToken > 1e12 && 248 | | longFundingFeeAmountPerSize.longToken <= 1e18 249 | | ) { 250 | | fl.log( 251 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e12 and 1e18" 252 | | ); 253 | | } 254 | | if ( 255 | | longFundingFeeAmountPerSize.longToken > 1e18 && 256 | | longFundingFeeAmountPerSize.longToken <= 1e24 257 | | ) { 258 | | fl.log( 259 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e18 and 1e24" 260 | | ); 261 | | } 262 | | if (longFundingFeeAmountPerSize.longToken > 1e24) { 263 | | fl.log( 264 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is greater than 1e24" 265 | | ); 266 | | } 267 | | if ( 268 | | longFundingFeeAmountPerSize.shortToken > 0 && 269 | | longFundingFeeAmountPerSize.shortToken <= 1e6 270 | | ) { 271 | | fl.log( 272 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 0 and 1e6" 273 | | ); 274 | | } 275 | | if ( 276 | | longFundingFeeAmountPerSize.shortToken > 1e6 && 277 | | longFundingFeeAmountPerSize.shortToken <= 1e12 278 | | ) { 279 | | fl.log( 280 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e6 and 1e12" 281 | | ); 282 | | } 283 | | if ( 284 | | longFundingFeeAmountPerSize.shortToken > 1e12 && 285 | | longFundingFeeAmountPerSize.shortToken <= 1e18 286 | | ) { 287 | | fl.log( 288 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e12 and 1e18" 289 | | ); 290 | | } 291 | | if ( 292 | | longFundingFeeAmountPerSize.shortToken > 1e18 && 293 | | longFundingFeeAmountPerSize.shortToken <= 1e24 294 | | ) { 295 | | fl.log( 296 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e18 and 1e24" 297 | | ); 298 | | } 299 | | if (longFundingFeeAmountPerSize.shortToken > 1e24) { 300 | | fl.log( 301 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is greater than 1e24" 302 | | ); 303 | | } 304 | | } 305 | | 306 | | function _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage_decreasePosition( 307 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSize 308 | | ) internal { 309 | | if ( 310 | | shortFundingFeeAmountPerSize.longToken == 0 && 311 | | shortFundingFeeAmountPerSize.shortToken == 0 312 | | ) { 313 | | fl.log( 314 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize is 0 for both longToken and shortToken" 315 | | ); 316 | | } 317 | | if ( 318 | | shortFundingFeeAmountPerSize.longToken > 0 && 319 | | shortFundingFeeAmountPerSize.longToken <= 1e6 320 | | ) { 321 | | fl.log( 322 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 0 and 1e6" 323 | | ); 324 | | } 325 | | if ( 326 | | shortFundingFeeAmountPerSize.longToken > 1e6 && 327 | | shortFundingFeeAmountPerSize.longToken <= 1e12 328 | | ) { 329 | | fl.log( 330 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e6 and 1e12" 331 | | ); 332 | | } 333 | | if ( 334 | | shortFundingFeeAmountPerSize.longToken > 1e12 && 335 | | shortFundingFeeAmountPerSize.longToken <= 1e18 336 | | ) { 337 | | fl.log( 338 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e12 and 1e18" 339 | | ); 340 | | } 341 | | if ( 342 | | shortFundingFeeAmountPerSize.longToken > 1e18 && 343 | | shortFundingFeeAmountPerSize.longToken <= 1e24 344 | | ) { 345 | | fl.log( 346 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e18 and 1e24" 347 | | ); 348 | | } 349 | | if (shortFundingFeeAmountPerSize.longToken > 1e24) { 350 | | fl.log( 351 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is greater than 1e24" 352 | | ); 353 | | } 354 | | if ( 355 | | shortFundingFeeAmountPerSize.shortToken > 0 && 356 | | shortFundingFeeAmountPerSize.shortToken <= 1e6 357 | | ) { 358 | | fl.log( 359 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 0 and 1e6" 360 | | ); 361 | | } 362 | | if ( 363 | | shortFundingFeeAmountPerSize.shortToken > 1e6 && 364 | | shortFundingFeeAmountPerSize.shortToken <= 1e12 365 | | ) { 366 | | fl.log( 367 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e6 and 1e12" 368 | | ); 369 | | } 370 | | if ( 371 | | shortFundingFeeAmountPerSize.shortToken > 1e12 && 372 | | shortFundingFeeAmountPerSize.shortToken <= 1e18 373 | | ) { 374 | | fl.log( 375 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e12 and 1e18" 376 | | ); 377 | | } 378 | | if ( 379 | | shortFundingFeeAmountPerSize.shortToken > 1e18 && 380 | | shortFundingFeeAmountPerSize.shortToken <= 1e24 381 | | ) { 382 | | fl.log( 383 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e18 and 1e24" 384 | | ); 385 | | } 386 | | if (shortFundingFeeAmountPerSize.shortToken > 1e24) { 387 | | fl.log( 388 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is greater than 1e24" 389 | | ); 390 | | } 391 | | } 392 | | 393 | | function _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage_decreasePosition( 394 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSize 395 | | ) internal { 396 | | if ( 397 | | longClaimableFundingAmountPerSize.longToken == 0 && 398 | | longClaimableFundingAmountPerSize.shortToken == 0 399 | | ) { 400 | | fl.log( 401 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize is 0 for both longToken and shortToken" 402 | | ); 403 | | } 404 | | if ( 405 | | longClaimableFundingAmountPerSize.longToken > 0 && 406 | | longClaimableFundingAmountPerSize.longToken <= 1e6 407 | | ) { 408 | | fl.log( 409 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 0 and 1e6" 410 | | ); 411 | | } 412 | | if ( 413 | | longClaimableFundingAmountPerSize.longToken > 1e6 && 414 | | longClaimableFundingAmountPerSize.longToken <= 1e12 415 | | ) { 416 | | fl.log( 417 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e6 and 1e12" 418 | | ); 419 | | } 420 | | if ( 421 | | longClaimableFundingAmountPerSize.longToken > 1e12 && 422 | | longClaimableFundingAmountPerSize.longToken <= 1e18 423 | | ) { 424 | | fl.log( 425 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e12 and 1e18" 426 | | ); 427 | | } 428 | | if ( 429 | | longClaimableFundingAmountPerSize.longToken > 1e18 && 430 | | longClaimableFundingAmountPerSize.longToken <= 1e24 431 | | ) { 432 | | fl.log( 433 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e18 and 1e24" 434 | | ); 435 | | } 436 | | if (longClaimableFundingAmountPerSize.longToken > 1e24) { 437 | | fl.log( 438 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is greater than 1e24" 439 | | ); 440 | | } 441 | | if ( 442 | | longClaimableFundingAmountPerSize.shortToken > 0 && 443 | | longClaimableFundingAmountPerSize.shortToken <= 1e6 444 | | ) { 445 | | fl.log( 446 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 0 and 1e6" 447 | | ); 448 | | } 449 | | if ( 450 | | longClaimableFundingAmountPerSize.shortToken > 1e6 && 451 | | longClaimableFundingAmountPerSize.shortToken <= 1e12 452 | | ) { 453 | | fl.log( 454 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12" 455 | | ); 456 | | } 457 | | if ( 458 | | longClaimableFundingAmountPerSize.shortToken > 1e12 && 459 | | longClaimableFundingAmountPerSize.shortToken <= 1e18 460 | | ) { 461 | | fl.log( 462 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18" 463 | | ); 464 | | } 465 | | if ( 466 | | longClaimableFundingAmountPerSize.shortToken > 1e18 && 467 | | longClaimableFundingAmountPerSize.shortToken <= 1e24 468 | | ) { 469 | | fl.log( 470 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24" 471 | | ); 472 | | } 473 | | if (longClaimableFundingAmountPerSize.shortToken > 1e24) { 474 | | fl.log( 475 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is greater than 1e24" 476 | | ); 477 | | } 478 | | } 479 | | 480 | | function _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage_decreasePosition( 481 | | MarketUtils.CollateralType memory shortClaimableFundingAmountPerSize 482 | | ) internal { 483 | | if ( 484 | | shortClaimableFundingAmountPerSize.longToken == 0 && 485 | | shortClaimableFundingAmountPerSize.shortToken == 0 486 | | ) { 487 | | fl.log( 488 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize is 0 for both longToken and shortToken" 489 | | ); 490 | | } 491 | | if ( 492 | | shortClaimableFundingAmountPerSize.longToken > 0 && 493 | | shortClaimableFundingAmountPerSize.longToken <= 1e6 494 | | ) { 495 | | fl.log( 496 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 0 and 1e6" 497 | | ); 498 | | } 499 | | if ( 500 | | shortClaimableFundingAmountPerSize.longToken > 1e6 && 501 | | shortClaimableFundingAmountPerSize.longToken <= 1e12 502 | | ) { 503 | | fl.log( 504 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e6 and 1e12" 505 | | ); 506 | | } 507 | | if ( 508 | | shortClaimableFundingAmountPerSize.longToken > 1e12 && 509 | | shortClaimableFundingAmountPerSize.longToken <= 1e18 510 | | ) { 511 | | fl.log( 512 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e12 and 1e18" 513 | | ); 514 | | } 515 | | if ( 516 | | shortClaimableFundingAmountPerSize.longToken > 1e18 && 517 | | shortClaimableFundingAmountPerSize.longToken <= 1e24 518 | | ) { 519 | | fl.log( 520 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e18 and 1e24" 521 | | ); 522 | | } 523 | | if (shortClaimableFundingAmountPerSize.longToken > 1e24) { 524 | | fl.log( 525 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is greater than 1e24" 526 | | ); 527 | | } 528 | | if ( 529 | | shortClaimableFundingAmountPerSize.shortToken > 0 && 530 | | shortClaimableFundingAmountPerSize.shortToken <= 1e6 531 | | ) { 532 | | fl.log( 533 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 0 and 1e6" 534 | | ); 535 | | } 536 | | if ( 537 | | shortClaimableFundingAmountPerSize.shortToken > 1e6 && 538 | | shortClaimableFundingAmountPerSize.shortToken <= 1e12 539 | | ) { 540 | | fl.log( 541 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12" 542 | | ); 543 | | } 544 | | if ( 545 | | shortClaimableFundingAmountPerSize.shortToken > 1e12 && 546 | | shortClaimableFundingAmountPerSize.shortToken <= 1e18 547 | | ) { 548 | | fl.log( 549 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18" 550 | | ); 551 | | } 552 | | if ( 553 | | shortClaimableFundingAmountPerSize.shortToken > 1e18 && 554 | | shortClaimableFundingAmountPerSize.shortToken <= 1e24 555 | | ) { 556 | | fl.log( 557 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24" 558 | | ); 559 | | } 560 | | if (shortClaimableFundingAmountPerSize.shortToken > 1e24) { 561 | | fl.log( 562 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is greater than 1e24" 563 | | ); 564 | | } 565 | | } 566 | | 567 | | function _logMarketInfoNextFundingLongsPayShortsCoverage_decreasePosition( 568 | | bool longsPayShorts 569 | | ) internal { 570 | | if (longsPayShorts) { 571 | | fl.log("MarketInfo nextFunding longsPayShorts is true"); 572 | | } else { 573 | | fl.log("MarketInfo nextFunding longsPayShorts is false"); 574 | | } 575 | | } 576 | | 577 | | function _logMarketInfoNextFundingFundingFactorPerSecondCoverage_decreasePosition( 578 | | uint256 fundingFactorPerSecond 579 | | ) internal { 580 | | if (fundingFactorPerSecond == 0) { 581 | | fl.log("MarketInfo nextFunding fundingFactorPerSecond is 0"); 582 | | } 583 | | if (fundingFactorPerSecond > 0 && fundingFactorPerSecond <= 1e6) { 584 | | fl.log( 585 | | "MarketInfo nextFunding fundingFactorPerSecond is between 0 and 1e6" 586 | | ); 587 | | } 588 | | if (fundingFactorPerSecond > 1e6 && fundingFactorPerSecond <= 1e12) { 589 | | fl.log( 590 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e6 and 1e12" 591 | | ); 592 | | } 593 | | if (fundingFactorPerSecond > 1e12 && fundingFactorPerSecond <= 1e18) { 594 | | fl.log( 595 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e12 and 1e18" 596 | | ); 597 | | } 598 | | if (fundingFactorPerSecond > 1e18 && fundingFactorPerSecond <= 1e24) { 599 | | fl.log( 600 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e18 and 1e24" 601 | | ); 602 | | } 603 | | if (fundingFactorPerSecond > 1e24) { 604 | | fl.log( 605 | | "MarketInfo nextFunding fundingFactorPerSecond is greater than 1e24" 606 | | ); 607 | | } 608 | | } 609 | | 610 | | function _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage_decreasePosition( 611 | | int256 nextSavedFundingFactorPerSecond 612 | | ) internal { 613 | | if (nextSavedFundingFactorPerSecond == 0) { 614 | | fl.log( 615 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is 0" 616 | | ); 617 | | } 618 | | if ( 619 | | nextSavedFundingFactorPerSecond > 0 && 620 | | nextSavedFundingFactorPerSecond <= 1e6 621 | | ) { 622 | | fl.log( 623 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and 1e6" 624 | | ); 625 | | } 626 | | if ( 627 | | nextSavedFundingFactorPerSecond > 1e6 && 628 | | nextSavedFundingFactorPerSecond <= 1e12 629 | | ) { 630 | | fl.log( 631 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e6 and 1e12" 632 | | ); 633 | | } 634 | | if ( 635 | | nextSavedFundingFactorPerSecond > 1e12 && 636 | | nextSavedFundingFactorPerSecond <= 1e18 637 | | ) { 638 | | fl.log( 639 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e12 and 1e18" 640 | | ); 641 | | } 642 | | if ( 643 | | nextSavedFundingFactorPerSecond > 1e18 && 644 | | nextSavedFundingFactorPerSecond <= 1e24 645 | | ) { 646 | | fl.log( 647 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e18 and 1e24" 648 | | ); 649 | | } 650 | | if (nextSavedFundingFactorPerSecond > 1e24) { 651 | | fl.log( 652 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is greater than 1e24" 653 | | ); 654 | | } 655 | | if ( 656 | | nextSavedFundingFactorPerSecond < 0 && 657 | | nextSavedFundingFactorPerSecond >= -1e6 658 | | ) { 659 | | fl.log( 660 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and -1e6" 661 | | ); 662 | | } 663 | | if ( 664 | | nextSavedFundingFactorPerSecond < -1e6 && 665 | | nextSavedFundingFactorPerSecond >= -1e12 666 | | ) { 667 | | fl.log( 668 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e6 and -1e12" 669 | | ); 670 | | } 671 | | if ( 672 | | nextSavedFundingFactorPerSecond < -1e12 && 673 | | nextSavedFundingFactorPerSecond >= -1e18 674 | | ) { 675 | | fl.log( 676 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e12 and -1e18" 677 | | ); 678 | | } 679 | | if ( 680 | | nextSavedFundingFactorPerSecond < -1e18 && 681 | | nextSavedFundingFactorPerSecond >= -1e24 682 | | ) { 683 | | fl.log( 684 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e18 and -1e24" 685 | | ); 686 | | } 687 | | if (nextSavedFundingFactorPerSecond < -1e24) { 688 | | fl.log( 689 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is less than -1e24" 690 | | ); 691 | | } 692 | | } 693 | | 694 | | function _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage_decreasePosition( 695 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSizeDelta 696 | | ) internal { 697 | | if ( 698 | | longFundingFeeAmountPerSizeDelta.longToken == 0 && 699 | | longFundingFeeAmountPerSizeDelta.shortToken == 0 700 | | ) { 701 | | fl.log( 702 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken" 703 | | ); 704 | | } 705 | | if ( 706 | | longFundingFeeAmountPerSizeDelta.longToken > 0 && 707 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e6 708 | | ) { 709 | | fl.log( 710 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6" 711 | | ); 712 | | } 713 | | if ( 714 | | longFundingFeeAmountPerSizeDelta.longToken > 1e6 && 715 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e12 716 | | ) { 717 | | fl.log( 718 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12" 719 | | ); 720 | | } 721 | | if ( 722 | | longFundingFeeAmountPerSizeDelta.longToken > 1e12 && 723 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e18 724 | | ) { 725 | | fl.log( 726 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18" 727 | | ); 728 | | } 729 | | if ( 730 | | longFundingFeeAmountPerSizeDelta.longToken > 1e18 && 731 | | longFundingFeeAmountPerSizeDelta.longToken <= 1e24 732 | | ) { 733 | | fl.log( 734 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24" 735 | | ); 736 | | } 737 | | if (longFundingFeeAmountPerSizeDelta.longToken > 1e24) { 738 | | fl.log( 739 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is greater than 1e24" 740 | | ); 741 | | } 742 | | if ( 743 | | longFundingFeeAmountPerSizeDelta.shortToken > 0 && 744 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e6 745 | | ) { 746 | | fl.log( 747 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6" 748 | | ); 749 | | } 750 | | if ( 751 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e6 && 752 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e12 753 | | ) { 754 | | fl.log( 755 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12" 756 | | ); 757 | | } 758 | | if ( 759 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e12 && 760 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e18 761 | | ) { 762 | | fl.log( 763 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18" 764 | | ); 765 | | } 766 | | if ( 767 | | longFundingFeeAmountPerSizeDelta.shortToken > 1e18 && 768 | | longFundingFeeAmountPerSizeDelta.shortToken <= 1e24 769 | | ) { 770 | | fl.log( 771 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24" 772 | | ); 773 | | } 774 | | if (longFundingFeeAmountPerSizeDelta.shortToken > 1e24) { 775 | | fl.log( 776 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is greater than 1e24" 777 | | ); 778 | | } 779 | | } 780 | | function _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage_decreasePosition( 781 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSizeDelta 782 | | ) internal { 783 | | if ( 784 | | shortFundingFeeAmountPerSizeDelta.longToken == 0 && 785 | | shortFundingFeeAmountPerSizeDelta.shortToken == 0 786 | | ) { 787 | | fl.log( 788 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken" 789 | | ); 790 | | } 791 | | if ( 792 | | shortFundingFeeAmountPerSizeDelta.longToken > 0 && 793 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e6 794 | | ) { 795 | | fl.log( 796 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6" 797 | | ); 798 | | } 799 | | if ( 800 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e6 && 801 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e12 802 | | ) { 803 | | fl.log( 804 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12" 805 | | ); 806 | | } 807 | | if ( 808 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e12 && 809 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e18 810 | | ) { 811 | | fl.log( 812 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18" 813 | | ); 814 | | } 815 | | if ( 816 | | shortFundingFeeAmountPerSizeDelta.longToken > 1e18 && 817 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e24 818 | | ) { 819 | | fl.log( 820 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24" 821 | | ); 822 | | } 823 | | if (shortFundingFeeAmountPerSizeDelta.longToken > 1e24) { 824 | | fl.log( 825 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is greater than 1e24" 826 | | ); 827 | | } 828 | | if ( 829 | | shortFundingFeeAmountPerSizeDelta.shortToken > 0 && 830 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e6 831 | | ) { 832 | | fl.log( 833 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6" 834 | | ); 835 | | } 836 | | if ( 837 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e6 && 838 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e12 839 | | ) { 840 | | fl.log( 841 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12" 842 | | ); 843 | | } 844 | | if ( 845 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e12 && 846 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e18 847 | | ) { 848 | | fl.log( 849 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18" 850 | | ); 851 | | } 852 | | if ( 853 | | shortFundingFeeAmountPerSizeDelta.shortToken > 1e18 && 854 | | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e24 855 | | ) { 856 | | fl.log( 857 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24" 858 | | ); 859 | | } 860 | | if (shortFundingFeeAmountPerSizeDelta.shortToken > 1e24) { 861 | | fl.log( 862 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is greater than 1e24" 863 | | ); 864 | | } 865 | | } 866 | | 867 | | function _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition( 868 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSizeDelta 869 | | ) internal { 870 | | if ( 871 | | longClaimableFundingAmountPerSizeDelta.longToken == 0 && 872 | | longClaimableFundingAmountPerSizeDelta.shortToken == 0 873 | | ) { 874 | | fl.log( 875 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken" 876 | | ); 877 | | } 878 | | if ( 879 | | longClaimableFundingAmountPerSizeDelta.longToken > 0 && 880 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e6 881 | | ) { 882 | | fl.log( 883 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6" 884 | | ); 885 | | } 886 | | if ( 887 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e6 && 888 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e12 889 | | ) { 890 | | fl.log( 891 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12" 892 | | ); 893 | | } 894 | | if ( 895 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e12 && 896 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e18 897 | | ) { 898 | | fl.log( 899 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18" 900 | | ); 901 | | } 902 | | if ( 903 | | longClaimableFundingAmountPerSizeDelta.longToken > 1e18 && 904 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e24 905 | | ) { 906 | | fl.log( 907 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24" 908 | | ); 909 | | } 910 | | if (longClaimableFundingAmountPerSizeDelta.longToken > 1e24) { 911 | | fl.log( 912 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is greater than 1e24" 913 | | ); 914 | | } 915 | | if ( 916 | | longClaimableFundingAmountPerSizeDelta.shortToken > 0 && 917 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e6 918 | | ) { 919 | | fl.log( 920 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6" 921 | | ); 922 | | } 923 | | if ( 924 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e6 && 925 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e12 926 | | ) { 927 | | fl.log( 928 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12" 929 | | ); 930 | | } 931 | | if ( 932 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e12 && 933 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e18 934 | | ) { 935 | | fl.log( 936 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18" 937 | | ); 938 | | } 939 | | if ( 940 | | longClaimableFundingAmountPerSizeDelta.shortToken > 1e18 && 941 | | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e24 942 | | ) { 943 | | fl.log( 944 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24" 945 | | ); 946 | | } 947 | | if (longClaimableFundingAmountPerSizeDelta.shortToken > 1e24) { 948 | | fl.log( 949 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24" 950 | | ); 951 | | } 952 | | } 953 | | 954 | | function _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage_decreasePosition( 955 | | MarketUtils.CollateralType 956 | | memory shortClaimableFundingAmountPerSizeDelta 957 | | ) internal { 958 | | if ( 959 | | shortClaimableFundingAmountPerSizeDelta.longToken == 0 && 960 | | shortClaimableFundingAmountPerSizeDelta.shortToken == 0 961 | | ) { 962 | | fl.log( 963 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken" 964 | | ); 965 | | } 966 | | if ( 967 | | shortClaimableFundingAmountPerSizeDelta.longToken > 0 && 968 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e6 969 | | ) { 970 | | fl.log( 971 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6" 972 | | ); 973 | | } 974 | | if ( 975 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e6 && 976 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e12 977 | | ) { 978 | | fl.log( 979 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12" 980 | | ); 981 | | } 982 | | if ( 983 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e12 && 984 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e18 985 | | ) { 986 | | fl.log( 987 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18" 988 | | ); 989 | | } 990 | | if ( 991 | | shortClaimableFundingAmountPerSizeDelta.longToken > 1e18 && 992 | | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e24 993 | | ) { 994 | | fl.log( 995 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24" 996 | | ); 997 | | } 998 | | if (shortClaimableFundingAmountPerSizeDelta.longToken > 1e24) { 999 | | fl.log( 1000 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is greater than 1e24" 1001 | | ); 1002 | | } 1003 | | if ( 1004 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 0 && 1005 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e6 1006 | | ) { 1007 | | fl.log( 1008 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6" 1009 | | ); 1010 | | } 1011 | | if ( 1012 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e6 && 1013 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e12 1014 | | ) { 1015 | | fl.log( 1016 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12" 1017 | | ); 1018 | | } 1019 | | if ( 1020 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e12 && 1021 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e18 1022 | | ) { 1023 | | fl.log( 1024 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18" 1025 | | ); 1026 | | } 1027 | | if ( 1028 | | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e18 && 1029 | | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e24 1030 | | ) { 1031 | | fl.log( 1032 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24" 1033 | | ); 1034 | | } 1035 | | if (shortClaimableFundingAmountPerSizeDelta.shortToken > 1e24) { 1036 | | fl.log( 1037 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24" 1038 | | ); 1039 | | } 1040 | | } 1041 | | 1042 | | function _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage_decreasePosition( 1043 | | uint256 virtualPoolAmountForLongToken 1044 | | ) internal { 1045 | | if (virtualPoolAmountForLongToken == 0) { 1046 | | fl.log( 1047 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is 0" 1048 | | ); 1049 | | } 1050 | | if ( 1051 | | virtualPoolAmountForLongToken > 0 && 1052 | | virtualPoolAmountForLongToken <= 1e6 1053 | | ) { 1054 | | fl.log( 1055 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 0 and 1e6" 1056 | | ); 1057 | | } 1058 | | if ( 1059 | | virtualPoolAmountForLongToken > 1e6 && 1060 | | virtualPoolAmountForLongToken <= 1e12 1061 | | ) { 1062 | | fl.log( 1063 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e6 and 1e12" 1064 | | ); 1065 | | } 1066 | | if ( 1067 | | virtualPoolAmountForLongToken > 1e12 && 1068 | | virtualPoolAmountForLongToken <= 1e18 1069 | | ) { 1070 | | fl.log( 1071 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e12 and 1e18" 1072 | | ); 1073 | | } 1074 | | if ( 1075 | | virtualPoolAmountForLongToken > 1e18 && 1076 | | virtualPoolAmountForLongToken <= 1e24 1077 | | ) { 1078 | | fl.log( 1079 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e18 and 1e24" 1080 | | ); 1081 | | } 1082 | | if (virtualPoolAmountForLongToken > 1e24) { 1083 | | fl.log( 1084 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is greater than 1e24" 1085 | | ); 1086 | | } 1087 | | } 1088 | | 1089 | | function _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage_decreasePosition( 1090 | | uint256 virtualPoolAmountForShortToken 1091 | | ) internal { 1092 | | if (virtualPoolAmountForShortToken == 0) { 1093 | | fl.log( 1094 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is 0" 1095 | | ); 1096 | | } 1097 | | if ( 1098 | | virtualPoolAmountForShortToken > 0 && 1099 | | virtualPoolAmountForShortToken <= 1e6 1100 | | ) { 1101 | | fl.log( 1102 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 0 and 1e6" 1103 | | ); 1104 | | } 1105 | | if ( 1106 | | virtualPoolAmountForShortToken > 1e6 && 1107 | | virtualPoolAmountForShortToken <= 1e12 1108 | | ) { 1109 | | fl.log( 1110 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e6 and 1e12" 1111 | | ); 1112 | | } 1113 | | if ( 1114 | | virtualPoolAmountForShortToken > 1e12 && 1115 | | virtualPoolAmountForShortToken <= 1e18 1116 | | ) { 1117 | | fl.log( 1118 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e12 and 1e18" 1119 | | ); 1120 | | } 1121 | | if ( 1122 | | virtualPoolAmountForShortToken > 1e18 && 1123 | | virtualPoolAmountForShortToken <= 1e24 1124 | | ) { 1125 | | fl.log( 1126 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e18 and 1e24" 1127 | | ); 1128 | | } 1129 | | if (virtualPoolAmountForShortToken > 1e24) { 1130 | | fl.log( 1131 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is greater than 1e24" 1132 | | ); 1133 | | } 1134 | | } 1135 | | 1136 | | function _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage_decreasePosition( 1137 | | int256 virtualInventoryForPositions 1138 | | ) internal { 1139 | | if (virtualInventoryForPositions == 0) { 1140 | | fl.log( 1141 | | "MarketInfo virtualInventory virtualInventoryForPositions is 0" 1142 | | ); 1143 | | } 1144 | | if ( 1145 | | virtualInventoryForPositions > 0 && 1146 | | virtualInventoryForPositions <= 1e6 1147 | | ) { 1148 | | fl.log( 1149 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and 1e6" 1150 | | ); 1151 | | } 1152 | | if ( 1153 | | virtualInventoryForPositions > 1e6 && 1154 | | virtualInventoryForPositions <= 1e12 1155 | | ) { 1156 | | fl.log( 1157 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e6 and 1e12" 1158 | | ); 1159 | | } 1160 | | if ( 1161 | | virtualInventoryForPositions > 1e12 && 1162 | | virtualInventoryForPositions <= 1e18 1163 | | ) { 1164 | | fl.log( 1165 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e12 and 1e18" 1166 | | ); 1167 | | } 1168 | | if ( 1169 | | virtualInventoryForPositions > 1e18 && 1170 | | virtualInventoryForPositions <= 1e24 1171 | | ) { 1172 | | fl.log( 1173 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e18 and 1e24" 1174 | | ); 1175 | | } 1176 | | if (virtualInventoryForPositions > 1e24) { 1177 | | fl.log( 1178 | | "MarketInfo virtualInventory virtualInventoryForPositions is greater than 1e24" 1179 | | ); 1180 | | } 1181 | | if ( 1182 | | virtualInventoryForPositions < 0 && 1183 | | virtualInventoryForPositions >= -1e6 1184 | | ) { 1185 | | fl.log( 1186 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and -1e6" 1187 | | ); 1188 | | } 1189 | | if ( 1190 | | virtualInventoryForPositions < -1e6 && 1191 | | virtualInventoryForPositions >= -1e12 1192 | | ) { 1193 | | fl.log( 1194 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e6 and -1e12" 1195 | | ); 1196 | | } 1197 | | if ( 1198 | | virtualInventoryForPositions < -1e12 && 1199 | | virtualInventoryForPositions >= -1e18 1200 | | ) { 1201 | | fl.log( 1202 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e12 and -1e18" 1203 | | ); 1204 | | } 1205 | | if ( 1206 | | virtualInventoryForPositions < -1e18 && 1207 | | virtualInventoryForPositions >= -1e24 1208 | | ) { 1209 | | fl.log( 1210 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e18 and -1e24" 1211 | | ); 1212 | | } 1213 | | if (virtualInventoryForPositions < -1e24) { 1214 | | fl.log( 1215 | | "MarketInfo virtualInventory virtualInventoryForPositions is less than -1e24" 1216 | | ); 1217 | | } 1218 | | } 1219 | | 1220 | | function _logMarketInfoIsDisabledCoverage_decreasePosition( 1221 | | bool isDisabled 1222 | | ) internal { 1223 | | if (isDisabled) { 1224 | | fl.log("MarketInfo isDisabled is true"); 1225 | | } else { 1226 | | fl.log("MarketInfo isDisabled is false"); 1227 | | } 1228 | | } 1229 | | } 1230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/IncreasePositionInfoCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract IncreasePositionInfoCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ INCREASE POSITION 10 | | // __^ __( \.__) ) GET POSITION INFO 11 | | // (@)<_____>__(_____)____/ COVERAGE 12 | | 13 | * | function _checkIncreaseOrderAndGetPositionCoverage( 14 | | Position.Props memory position 15 | | ) internal { 16 | * | _logPositionAccountCoverage(position.addresses.account); 17 | * | _logPositionMarketCoverage(position.addresses.market); 18 | * | _logPositionCollateralTokenCoverage(position.addresses.collateralToken); 19 | * | _logPositionSizeInUsdCoverage(position.numbers.sizeInUsd); 20 | * | _logPositionSizeInTokensCoverage(position.numbers.sizeInTokens); 21 | * | _logPositionCollateralAmountCoverage(position.numbers.collateralAmount); 22 | * | _logPositionBorrowingFactorCoverage(position.numbers.borrowingFactor); 23 | * | _logPositionFundingFeeAmountPerSizeCoverage( 24 | * | position.numbers.fundingFeeAmountPerSize 25 | | ); 26 | * | _logPositionLongTokenClaimableFundingAmountPerSizeCoverage( 27 | * | position.numbers.longTokenClaimableFundingAmountPerSize 28 | | ); 29 | * | _logPositionShortTokenClaimableFundingAmountPerSizeCoverage( 30 | * | position.numbers.shortTokenClaimableFundingAmountPerSize 31 | | ); 32 | * | _logPositionIncreasedAtBlockCoverage(position.numbers.increasedAtBlock); 33 | * | _logPositionDecreasedAtBlockCoverage(position.numbers.decreasedAtBlock); 34 | * | _logPositionIncreasedAtTimeCoverage(position.numbers.increasedAtTime); 35 | * | _logPositionDecreasedAtTimeCoverage(position.numbers.decreasedAtTime); 36 | * | _logPositionIsLongCoverage(position.flags.isLong); 37 | | } 38 | | 39 | * | function _checkIncreaseOrderAndGetPositionInfoCoverage( 40 | | ReaderUtils.PositionInfo memory positionInfo 41 | | ) internal { 42 | | // Position.Props logged above 43 | * | _logPositionFeesReferralCodeCoverage( 44 | * | positionInfo.fees.referral.referralCode 45 | | ); 46 | * | _logPositionFeesAffiliateCoverage(positionInfo.fees.referral.affiliate); 47 | * | _logPositionFeesTraderCoverage(positionInfo.fees.referral.trader); 48 | * | _logPositionFeesTotalRebateFactorCoverage( 49 | * | positionInfo.fees.referral.totalRebateFactor 50 | | ); 51 | * | _logPositionFeesTraderDiscountFactorCoverage( 52 | * | positionInfo.fees.referral.traderDiscountFactor 53 | | ); 54 | * | _logPositionFeesTotalRebateAmountCoverage( 55 | * | positionInfo.fees.referral.totalRebateAmount 56 | | ); 57 | * | _logPositionFeesTraderDiscountAmountCoverage( 58 | * | positionInfo.fees.referral.traderDiscountAmount 59 | | ); 60 | * | _logPositionFeesAffiliateRewardAmountCoverage( 61 | * | positionInfo.fees.referral.affiliateRewardAmount 62 | | ); 63 | * | _logPositionFeesFundingFeeAmountCoverage( 64 | * | positionInfo.fees.funding.fundingFeeAmount 65 | | ); 66 | * | _logPositionFeesClaimableLongTokenAmountCoverage( 67 | * | positionInfo.fees.funding.claimableLongTokenAmount 68 | | ); 69 | * | _logPositionFeesClaimableShortTokenAmountCoverage( 70 | * | positionInfo.fees.funding.claimableShortTokenAmount 71 | | ); 72 | * | _logPositionFeesLatestFundingFeeAmountPerSizeCoverage( 73 | * | positionInfo.fees.funding.latestFundingFeeAmountPerSize 74 | | ); 75 | * | _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage( 76 | * | positionInfo 77 | | .fees 78 | | .funding 79 | | .latestLongTokenClaimableFundingAmountPerSize 80 | | ); 81 | * | _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage( 82 | * | positionInfo 83 | | .fees 84 | | .funding 85 | | .latestShortTokenClaimableFundingAmountPerSize 86 | | ); 87 | * | _logPositionFeesBorrowingFeeUsdCoverage( 88 | * | positionInfo.fees.borrowing.borrowingFeeUsd 89 | | ); 90 | * | _logPositionFeesBorrowingFeeAmountCoverage( 91 | * | positionInfo.fees.borrowing.borrowingFeeAmount 92 | | ); 93 | * | _logPositionFeesBorrowingFeeReceiverFactorCoverage( 94 | * | positionInfo.fees.borrowing.borrowingFeeReceiverFactor 95 | | ); 96 | * | _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage( 97 | * | positionInfo.fees.borrowing.borrowingFeeAmountForFeeReceiver 98 | | ); 99 | * | _logPositionFeesUiFeeReceiverCoverage( 100 | * | positionInfo.fees.ui.uiFeeReceiver 101 | | ); 102 | * | _logPositionFeesUiFeeReceiverFactorCoverage( 103 | * | positionInfo.fees.ui.uiFeeReceiverFactor 104 | | ); 105 | * | _logPositionFeesUiFeeAmountCoverage(positionInfo.fees.ui.uiFeeAmount); 106 | * | _logPositionFeesCollateralTokenPriceCoverage( 107 | * | positionInfo.fees.collateralTokenPrice.max 108 | | ); 109 | * | _logPositionFeesPositionFeeFactorCoverage( 110 | * | positionInfo.fees.positionFeeFactor 111 | | ); 112 | * | _logPositionFeesProtocolFeeAmountCoverage( 113 | * | positionInfo.fees.protocolFeeAmount 114 | | ); 115 | * | _logPositionFeesPositionFeeReceiverFactorCoverage( 116 | * | positionInfo.fees.positionFeeReceiverFactor 117 | | ); 118 | * | _logPositionFeesFeeReceiverAmountCoverage( 119 | * | positionInfo.fees.feeReceiverAmount 120 | | ); 121 | * | _logPositionFeesFeeAmountForPoolCoverage( 122 | * | positionInfo.fees.feeAmountForPool 123 | | ); 124 | * | _logPositionFeesPositionFeeAmountForPoolCoverage( 125 | * | positionInfo.fees.positionFeeAmountForPool 126 | | ); 127 | * | _logPositionFeesPositionFeeAmountCoverage( 128 | * | positionInfo.fees.positionFeeAmount 129 | | ); 130 | * | _logPositionFeesTotalCostAmountExcludingFundingCoverage( 131 | * | positionInfo.fees.totalCostAmountExcludingFunding 132 | | ); 133 | * | _logPositionFeesTotalCostAmountCoverage( 134 | * | positionInfo.fees.totalCostAmount 135 | | ); 136 | | 137 | | // ExecutionPriceResult 138 | * | _logExecutionPriceResultPriceImpactUsdCoverage( 139 | * | positionInfo.executionPriceResult.priceImpactUsd 140 | | ); 141 | * | _logExecutionPriceResultPriceImpactDiffUsdCoverage( 142 | * | positionInfo.executionPriceResult.priceImpactDiffUsd 143 | | ); 144 | * | _logExecutionPriceResultExecutionPriceCoverage( 145 | * | positionInfo.executionPriceResult.executionPrice 146 | | ); 147 | | 148 | * | _logPositionInfoBasePnlUsdCoverage(positionInfo.basePnlUsd); 149 | * | _logPositionInfoUncappedBasePnlUsdCoverage( 150 | * | positionInfo.uncappedBasePnlUsd 151 | | ); 152 | * | _logPositionInfoPnlAfterPriceImpactUsdCoverage( 153 | * | positionInfo.pnlAfterPriceImpactUsd 154 | | ); 155 | | } 156 | | 157 | * | function _logPositionAccountCoverage(address account) internal { 158 | * | if (account == USER0) { 159 | * | fl.log("PositionFees account USER0 hit"); 160 | | } 161 | * | if (account == USER1) { 162 | * | fl.log("PositionFees account USER1 hit"); 163 | | } 164 | * | if (account == USER2) { 165 | * | fl.log("PositionFees account USER2 hit"); 166 | | } 167 | * | if (account == USER3) { 168 | * | fl.log("PositionFees account USER3 hit"); 169 | | } 170 | * | if (account == USER4) { 171 | * | fl.log("PositionFees account USER4 hit"); 172 | | } 173 | * | if (account == USER5) { 174 | * | fl.log("PositionFees account USER5 hit"); 175 | | } 176 | * | if (account == USER6) { 177 | * | fl.log("PositionFees account USER6 hit"); 178 | | } 179 | * | if (account == USER7) { 180 | * | fl.log("PositionFees account USER7 hit"); 181 | | } 182 | * | if (account == USER8) { 183 | * | fl.log("PositionFees account USER8 hit"); 184 | | } 185 | * | if (account == USER9) { 186 | * | fl.log("PositionFees account USER9 hit"); 187 | | } 188 | * | if (account == USER10) { 189 | * | fl.log("PositionFees account USER10 hit"); 190 | | } 191 | * | if (account == USER11) { 192 | * | fl.log("PositionFees account USER11 hit"); 193 | | } 194 | * | if (account == USER12) { 195 | * | fl.log("PositionFees account USER12 hit"); 196 | | } 197 | * | if (account == USER13) { 198 | * | fl.log("PositionFees account USER13 hit"); 199 | | } 200 | | } 201 | * | function _logPositionMarketCoverage(address market) internal { 202 | * | if (market == address(market_0_WETH_USDC)) { 203 | | fl.log("Position market market_0_WETH_USDC hit"); 204 | | } 205 | | 206 | * | if (market == address(market_WBTC_WBTC_USDC)) { 207 | * | fl.log("Position market market_WBTC_WBTC_USDC hit"); 208 | | } 209 | * | if (market == address(market_WETH_WETH_USDC)) { 210 | * | fl.log("Position market market_WETH_WETH_USDC hit"); 211 | | } 212 | * | if (market == address(market_WETH_WETH_USDT)) { 213 | * | fl.log("Position market market_WETH_WETH_USDT hit"); 214 | | } 215 | | } 216 | | 217 | * | function _logPositionCollateralTokenCoverage( 218 | | address collateralToken 219 | | ) internal { 220 | * | if (collateralToken == address(WETH)) { 221 | * | fl.log("Position collateralToken is WETH"); 222 | | } 223 | * | if (collateralToken == address(WBTC)) { 224 | * | fl.log("Position collateralToken is WBTC"); 225 | | } 226 | * | if (collateralToken == address(USDC)) { 227 | * | fl.log("Position collateralToken is USDC"); 228 | | } 229 | * | if (collateralToken == address(USDT)) { 230 | * | fl.log("Position collateralToken is USDT"); 231 | | } 232 | * | if (collateralToken == address(SOL)) { 233 | | fl.log("Position collateralToken is SOL"); 234 | | } 235 | | } 236 | | 237 | * | function _logPositionSizeInUsdCoverage(uint256 sizeInUsd) internal { 238 | * | if (sizeInUsd == 0) { 239 | | fl.log("Position sizeInUsd is 0"); 240 | | } 241 | * | if (sizeInUsd > 0 && sizeInUsd <= 1e6) { 242 | | fl.log("Position sizeInUsd is between 0 and 1e6"); 243 | | } 244 | * | if (sizeInUsd > 1e6 && sizeInUsd <= 1e12) { 245 | | fl.log("Position sizeInUsd is between 1e6 and 1e12"); 246 | | } 247 | * | if (sizeInUsd > 1e12 && sizeInUsd <= 1e18) { 248 | | fl.log("Position sizeInUsd is between 1e12 and 1e18"); 249 | | } 250 | * | if (sizeInUsd > 1e18 && sizeInUsd <= 1e24) { 251 | | fl.log("Position sizeInUsd is between 1e18 and 1e24"); 252 | | } 253 | * | if (sizeInUsd > 1e24) { 254 | * | fl.log("Position sizeInUsd is greater than 1e24"); 255 | | } 256 | | } 257 | | 258 | * | function _logPositionSizeInTokensCoverage(uint256 sizeInTokens) internal { 259 | * | if (sizeInTokens == 0) { 260 | | fl.log("Position sizeInTokens is 0"); 261 | | } 262 | * | if (sizeInTokens > 0 && sizeInTokens <= 1e6) { 263 | * | fl.log("Position sizeInTokens is between 0 and 1e6"); 264 | | } 265 | * | if (sizeInTokens > 1e6 && sizeInTokens <= 1e12) { 266 | * | fl.log("Position sizeInTokens is between 1e6 and 1e12"); 267 | | } 268 | * | if (sizeInTokens > 1e12 && sizeInTokens <= 1e18) { 269 | * | fl.log("Position sizeInTokens is between 1e12 and 1e18"); 270 | | } 271 | * | if (sizeInTokens > 1e18 && sizeInTokens <= 1e24) { 272 | * | fl.log("Position sizeInTokens is between 1e18 and 1e24"); 273 | | } 274 | * | if (sizeInTokens > 1e24) { 275 | | fl.log("Position sizeInTokens is greater than 1e24"); 276 | | } 277 | | } 278 | | 279 | * | function _logPositionCollateralAmountCoverage( 280 | | uint256 collateralAmount 281 | | ) internal { 282 | * | if (collateralAmount == 0) { 283 | | fl.log("Position collateralAmount is 0"); 284 | | } 285 | * | if (collateralAmount > 0 && collateralAmount <= 1e6) { 286 | * | fl.log("Position collateralAmount is between 0 and 1e6"); 287 | | } 288 | * | if (collateralAmount > 1e6 && collateralAmount <= 1e12) { 289 | * | fl.log("Position collateralAmount is between 1e6 and 1e12"); 290 | | } 291 | * | if (collateralAmount > 1e12 && collateralAmount <= 1e18) { 292 | * | fl.log("Position collateralAmount is between 1e12 and 1e18"); 293 | | } 294 | * | if (collateralAmount > 1e18 && collateralAmount <= 1e24) { 295 | * | fl.log("Position collateralAmount is between 1e18 and 1e24"); 296 | | } 297 | * | if (collateralAmount > 1e24) { 298 | | fl.log("Position collateralAmount is greater than 1e24"); 299 | | } 300 | | } 301 | | 302 | * | function _logPositionBorrowingFactorCoverage( 303 | | uint256 borrowingFactor 304 | | ) internal { 305 | * | if (borrowingFactor == 0) { 306 | * | fl.log("Position borrowingFactor is 0"); 307 | | } 308 | * | if (borrowingFactor > 0 && borrowingFactor <= 1e6) { 309 | | fl.log("Position borrowingFactor is between 0 and 1e6"); 310 | | } 311 | * | if (borrowingFactor > 1e6 && borrowingFactor <= 1e12) { 312 | | fl.log("Position borrowingFactor is between 1e6 and 1e12"); 313 | | } 314 | * | if (borrowingFactor > 1e12 && borrowingFactor <= 1e18) { 315 | | fl.log("Position borrowingFactor is between 1e12 and 1e18"); 316 | | } 317 | * | if (borrowingFactor > 1e18 && borrowingFactor <= 1e24) { 318 | | fl.log("Position borrowingFactor is between 1e18 and 1e24"); 319 | | } 320 | * | if (borrowingFactor > 1e24) { 321 | | fl.log("Position borrowingFactor is greater than 1e24"); 322 | | } 323 | | } 324 | | 325 | * | function _logPositionFundingFeeAmountPerSizeCoverage( 326 | | uint256 fundingFeeAmountPerSize 327 | | ) internal { 328 | * | if (fundingFeeAmountPerSize == 0) { 329 | * | fl.log("Position fundingFeeAmountPerSize is 0"); 330 | | } 331 | * | if (fundingFeeAmountPerSize > 0 && fundingFeeAmountPerSize <= 1e6) { 332 | | fl.log("Position fundingFeeAmountPerSize is between 0 and 1e6"); 333 | | } 334 | * | if (fundingFeeAmountPerSize > 1e6 && fundingFeeAmountPerSize <= 1e12) { 335 | | fl.log("Position fundingFeeAmountPerSize is between 1e6 and 1e12"); 336 | | } 337 | * | if (fundingFeeAmountPerSize > 1e12 && fundingFeeAmountPerSize <= 1e18) { 338 | * | fl.log("Position fundingFeeAmountPerSize is between 1e12 and 1e18"); 339 | | } 340 | * | if (fundingFeeAmountPerSize > 1e18 && fundingFeeAmountPerSize <= 1e24) { 341 | * | fl.log("Position fundingFeeAmountPerSize is between 1e18 and 1e24"); 342 | | } 343 | * | if (fundingFeeAmountPerSize > 1e24) { 344 | * | fl.log("Position fundingFeeAmountPerSize is greater than 1e24"); 345 | | } 346 | | } 347 | | 348 | * | function _logPositionLongTokenClaimableFundingAmountPerSizeCoverage( 349 | | uint256 longTokenClaimableFundingAmountPerSize 350 | | ) internal { 351 | * | if (longTokenClaimableFundingAmountPerSize == 0) { 352 | * | fl.log("Position longTokenClaimableFundingAmountPerSize is 0"); 353 | | } 354 | * | if ( 355 | * | longTokenClaimableFundingAmountPerSize > 0 && 356 | * | longTokenClaimableFundingAmountPerSize <= 1e6 357 | | ) { 358 | | fl.log( 359 | | "Position longTokenClaimableFundingAmountPerSize is between 0 and 1e6" 360 | | ); 361 | | } 362 | * | if ( 363 | * | longTokenClaimableFundingAmountPerSize > 1e6 && 364 | * | longTokenClaimableFundingAmountPerSize <= 1e12 365 | | ) { 366 | | fl.log( 367 | | "Position longTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 368 | | ); 369 | | } 370 | * | if ( 371 | * | longTokenClaimableFundingAmountPerSize > 1e12 && 372 | * | longTokenClaimableFundingAmountPerSize <= 1e18 373 | | ) { 374 | * | fl.log( 375 | | "Position longTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 376 | | ); 377 | | } 378 | * | if ( 379 | * | longTokenClaimableFundingAmountPerSize > 1e18 && 380 | * | longTokenClaimableFundingAmountPerSize <= 1e24 381 | | ) { 382 | * | fl.log( 383 | | "Position longTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 384 | | ); 385 | | } 386 | * | if (longTokenClaimableFundingAmountPerSize > 1e24) { 387 | * | fl.log( 388 | | "Position longTokenClaimableFundingAmountPerSize is greater than 1e24" 389 | | ); 390 | | } 391 | | } 392 | | 393 | * | function _logPositionShortTokenClaimableFundingAmountPerSizeCoverage( 394 | | uint256 shortTokenClaimableFundingAmountPerSize 395 | | ) internal { 396 | * | if (shortTokenClaimableFundingAmountPerSize == 0) { 397 | * | fl.log("Position shortTokenClaimableFundingAmountPerSize is 0"); 398 | | } 399 | * | if ( 400 | * | shortTokenClaimableFundingAmountPerSize > 0 && 401 | * | shortTokenClaimableFundingAmountPerSize <= 1e6 402 | | ) { 403 | | fl.log( 404 | | "Position shortTokenClaimableFundingAmountPerSize is between 0 and 1e6" 405 | | ); 406 | | } 407 | * | if ( 408 | * | shortTokenClaimableFundingAmountPerSize > 1e6 && 409 | * | shortTokenClaimableFundingAmountPerSize <= 1e12 410 | | ) { 411 | | fl.log( 412 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 413 | | ); 414 | | } 415 | * | if ( 416 | * | shortTokenClaimableFundingAmountPerSize > 1e12 && 417 | * | shortTokenClaimableFundingAmountPerSize <= 1e18 418 | | ) { 419 | * | fl.log( 420 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 421 | | ); 422 | | } 423 | * | if ( 424 | * | shortTokenClaimableFundingAmountPerSize > 1e18 && 425 | * | shortTokenClaimableFundingAmountPerSize <= 1e24 426 | | ) { 427 | * | fl.log( 428 | | "Position shortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 429 | | ); 430 | | } 431 | * | if (shortTokenClaimableFundingAmountPerSize > 1e24) { 432 | * | fl.log( 433 | | "Position shortTokenClaimableFundingAmountPerSize is greater than 1e24" 434 | | ); 435 | | } 436 | | } 437 | | 438 | * | function _logPositionIncreasedAtBlockCoverage( 439 | | uint256 increasedAtBlock 440 | | ) internal { 441 | * | if (increasedAtBlock == 0) { 442 | | fl.log("Position increasedAtBlock is 0"); 443 | | } else { 444 | * | fl.log("Position increasedAtBlock is non-zero"); 445 | | } 446 | | } 447 | | 448 | * | function _logPositionDecreasedAtBlockCoverage( 449 | | uint256 decreasedAtBlock 450 | | ) internal { 451 | * | if (decreasedAtBlock == 0) { 452 | * | fl.log("Position decreasedAtBlock is 0"); 453 | | } else { 454 | * | fl.log("Position decreasedAtBlock is non-zero"); 455 | | } 456 | | } 457 | | 458 | * | function _logPositionIncreasedAtTimeCoverage( 459 | | uint256 increasedAtTime 460 | | ) internal { 461 | * | if (increasedAtTime == 0) { 462 | | fl.log("Position increasedAtTime is 0"); 463 | | } else { 464 | * | fl.log("Position increasedAtTime is non-zero"); 465 | | } 466 | | } 467 | | 468 | * | function _logPositionDecreasedAtTimeCoverage( 469 | | uint256 decreasedAtTime 470 | | ) internal { 471 | * | if (decreasedAtTime == 0) { 472 | * | fl.log("Position decreasedAtTime is 0"); 473 | | } else { 474 | * | fl.log("Position decreasedAtTime is non-zero"); 475 | | } 476 | | } 477 | | 478 | * | function _logPositionIsLongCoverage(bool isLong) internal { 479 | * | if (isLong) { 480 | * | fl.log("Position isLong is true"); 481 | | } else { 482 | * | fl.log("Position isLong is false"); 483 | | } 484 | | } 485 | | 486 | * | function _logPositionFeesReferralCodeCoverage( 487 | | bytes32 referralCode 488 | | ) internal { 489 | * | if (referralCode == bytes32(0)) { 490 | * | fl.log("PositionFees referralCode is empty"); 491 | | } else { 492 | | fl.log("PositionFees referralCode is non-empty"); 493 | | } 494 | | } 495 | | 496 | * | function _logPositionFeesAffiliateCoverage(address affiliate) internal { 497 | * | if (affiliate == address(0)) { 498 | * | fl.log("PositionFees affiliate is address(0)"); 499 | | } else { 500 | | fl.log("PositionFees affiliate is non-zero address"); 501 | | } 502 | | } 503 | | 504 | * | function _logPositionFeesTraderCoverage(address trader) internal { 505 | * | if (trader == USER0) { 506 | * | fl.log("PositionFees trader USER0 hit"); 507 | | } 508 | * | if (trader == USER1) { 509 | * | fl.log("PositionFees trader USER1 hit"); 510 | | } 511 | * | if (trader == USER2) { 512 | * | fl.log("PositionFees trader USER2 hit"); 513 | | } 514 | * | if (trader == USER3) { 515 | * | fl.log("PositionFees trader USER3 hit"); 516 | | } 517 | * | if (trader == USER4) { 518 | * | fl.log("PositionFees trader USER4 hit"); 519 | | } 520 | * | if (trader == USER5) { 521 | * | fl.log("PositionFees trader USER5 hit"); 522 | | } 523 | * | if (trader == USER6) { 524 | * | fl.log("PositionFees trader USER6 hit"); 525 | | } 526 | * | if (trader == USER7) { 527 | * | fl.log("PositionFees trader USER7 hit"); 528 | | } 529 | * | if (trader == USER8) { 530 | * | fl.log("PositionFees trader USER8 hit"); 531 | | } 532 | * | if (trader == USER9) { 533 | * | fl.log("PositionFees trader USER9 hit"); 534 | | } 535 | * | if (trader == USER10) { 536 | * | fl.log("PositionFees trader USER10 hit"); 537 | | } 538 | * | if (trader == USER11) { 539 | * | fl.log("PositionFees trader USER11 hit"); 540 | | } 541 | * | if (trader == USER12) { 542 | * | fl.log("PositionFees trader USER12 hit"); 543 | | } 544 | * | if (trader == USER13) { 545 | * | fl.log("PositionFees trader USER13 hit"); 546 | | } 547 | | } 548 | | 549 | * | function _logPositionFeesTotalRebateFactorCoverage( 550 | | uint256 totalRebateFactor 551 | | ) internal { 552 | * | if (totalRebateFactor == 0) { 553 | * | fl.log("PositionFees totalRebateFactor is 0"); 554 | | } 555 | * | if (totalRebateFactor > 0 && totalRebateFactor <= 1e6) { 556 | | fl.log("PositionFees totalRebateFactor is between 0 and 1e6"); 557 | | } 558 | * | if (totalRebateFactor > 1e6 && totalRebateFactor <= 1e12) { 559 | | fl.log("PositionFees totalRebateFactor is between 1e6 and 1e12"); 560 | | } 561 | * | if (totalRebateFactor > 1e12 && totalRebateFactor <= 1e18) { 562 | | fl.log("PositionFees totalRebateFactor is between 1e12 and 1e18"); 563 | | } 564 | * | if (totalRebateFactor > 1e18 && totalRebateFactor <= 1e24) { 565 | | fl.log("PositionFees totalRebateFactor is between 1e18 and 1e24"); 566 | | } 567 | * | if (totalRebateFactor > 1e24) { 568 | | fl.log("PositionFees totalRebateFactor is greater than 1e24"); 569 | | } 570 | | } 571 | | 572 | * | function _logPositionFeesTraderDiscountFactorCoverage( 573 | | uint256 traderDiscountFactor 574 | | ) internal { 575 | * | if (traderDiscountFactor == 0) { 576 | * | fl.log("PositionFees traderDiscountFactor is 0"); 577 | | } 578 | * | if (traderDiscountFactor > 0 && traderDiscountFactor <= 1e6) { 579 | | fl.log("PositionFees traderDiscountFactor is between 0 and 1e6"); 580 | | } 581 | * | if (traderDiscountFactor > 1e6 && traderDiscountFactor <= 1e12) { 582 | | fl.log("PositionFees traderDiscountFactor is between 1e6 and 1e12"); 583 | | } 584 | * | if (traderDiscountFactor > 1e12 && traderDiscountFactor <= 1e18) { 585 | | fl.log( 586 | | "PositionFees traderDiscountFactor is between 1e12 and 1e18" 587 | | ); 588 | | } 589 | * | if (traderDiscountFactor > 1e18 && traderDiscountFactor <= 1e24) { 590 | | fl.log( 591 | | "PositionFees traderDiscountFactor is between 1e18 and 1e24" 592 | | ); 593 | | } 594 | * | if (traderDiscountFactor > 1e24) { 595 | | fl.log("PositionFees traderDiscountFactor is greater than 1e24"); 596 | | } 597 | | } 598 | | 599 | * | function _logPositionFeesTotalRebateAmountCoverage( 600 | | uint256 totalRebateAmount 601 | | ) internal { 602 | * | if (totalRebateAmount == 0) { 603 | * | fl.log("PositionFees totalRebateAmount is 0"); 604 | | } 605 | * | if (totalRebateAmount > 0 && totalRebateAmount <= 1e6) { 606 | | fl.log("PositionFees totalRebateAmount is between 0 and 1e6"); 607 | | } 608 | * | if (totalRebateAmount > 1e6 && totalRebateAmount <= 1e12) { 609 | | fl.log("PositionFees totalRebateAmount is between 1e6 and 1e12"); 610 | | } 611 | * | if (totalRebateAmount > 1e12 && totalRebateAmount <= 1e18) { 612 | | fl.log("PositionFees totalRebateAmount is between 1e12 and 1e18"); 613 | | } 614 | * | if (totalRebateAmount > 1e18 && totalRebateAmount <= 1e24) { 615 | | fl.log("PositionFees totalRebateAmount is between 1e18 and 1e24"); 616 | | } 617 | * | if (totalRebateAmount > 1e24) { 618 | | fl.log("PositionFees totalRebateAmount is greater than 1e24"); 619 | | } 620 | | } 621 | | 622 | * | function _logPositionFeesTraderDiscountAmountCoverage( 623 | | uint256 traderDiscountAmount 624 | | ) internal { 625 | * | if (traderDiscountAmount == 0) { 626 | * | fl.log("PositionFees traderDiscountAmount is 0"); 627 | | } 628 | * | if (traderDiscountAmount > 0 && traderDiscountAmount <= 1e6) { 629 | | fl.log("PositionFees traderDiscountAmount is between 0 and 1e6"); 630 | | } 631 | * | if (traderDiscountAmount > 1e6 && traderDiscountAmount <= 1e12) { 632 | | fl.log("PositionFees traderDiscountAmount is between 1e6 and 1e12"); 633 | | } 634 | * | if (traderDiscountAmount > 1e12 && traderDiscountAmount <= 1e18) { 635 | | fl.log( 636 | | "PositionFees traderDiscountAmount is between 1e12 and 1e18" 637 | | ); 638 | | } 639 | * | if (traderDiscountAmount > 1e18 && traderDiscountAmount <= 1e24) { 640 | | fl.log( 641 | | "PositionFees traderDiscountAmount is between 1e18 and 1e24" 642 | | ); 643 | | } 644 | * | if (traderDiscountAmount > 1e24) { 645 | | fl.log("PositionFees traderDiscountAmount is greater than 1e24"); 646 | | } 647 | | } 648 | | 649 | * | function _logPositionFeesAffiliateRewardAmountCoverage( 650 | | uint256 affiliateRewardAmount 651 | | ) internal { 652 | * | if (affiliateRewardAmount == 0) { 653 | * | fl.log("PositionFees affiliateRewardAmount is 0"); 654 | | } 655 | * | if (affiliateRewardAmount > 0 && affiliateRewardAmount <= 1e6) { 656 | | fl.log("PositionFees affiliateRewardAmount is between 0 and 1e6"); 657 | | } 658 | * | if (affiliateRewardAmount > 1e6 && affiliateRewardAmount <= 1e12) { 659 | | fl.log( 660 | | "PositionFees affiliateRewardAmount is between 1e6 and 1e12" 661 | | ); 662 | | } 663 | * | if (affiliateRewardAmount > 1e12 && affiliateRewardAmount <= 1e18) { 664 | | fl.log( 665 | | "PositionFees affiliateRewardAmount is between 1e12 and 1e18" 666 | | ); 667 | | } 668 | * | if (affiliateRewardAmount > 1e18 && affiliateRewardAmount <= 1e24) { 669 | | fl.log( 670 | | "PositionFees affiliateRewardAmount is between 1e18 and 1e24" 671 | | ); 672 | | } 673 | * | if (affiliateRewardAmount > 1e24) { 674 | | fl.log("PositionFees affiliateRewardAmount is greater than 1e24"); 675 | | } 676 | | } 677 | | 678 | * | function _logPositionFeesFundingFeeAmountCoverage( 679 | | uint256 fundingFeeAmount 680 | | ) internal { 681 | * | if (fundingFeeAmount == 0) { 682 | * | fl.log("PositionFees fundingFeeAmount is 0"); 683 | | } 684 | * | if (fundingFeeAmount > 0 && fundingFeeAmount <= 1e6) { 685 | * | fl.log("PositionFees fundingFeeAmount is between 0 and 1e6"); 686 | | } 687 | * | if (fundingFeeAmount > 1e6 && fundingFeeAmount <= 1e12) { 688 | * | fl.log("PositionFees fundingFeeAmount is between 1e6 and 1e12"); 689 | | } 690 | * | if (fundingFeeAmount > 1e12 && fundingFeeAmount <= 1e18) { 691 | * | fl.log("PositionFees fundingFeeAmount is between 1e12 and 1e18"); 692 | | } 693 | * | if (fundingFeeAmount > 1e18 && fundingFeeAmount <= 1e24) { 694 | * | fl.log("PositionFees fundingFeeAmount is between 1e18 and 1e24"); 695 | | } 696 | * | if (fundingFeeAmount > 1e24) { 697 | | fl.log("PositionFees fundingFeeAmount is greater than 1e24"); 698 | | } 699 | | } 700 | | 701 | * | function _logPositionFeesClaimableLongTokenAmountCoverage( 702 | | uint256 claimableLongTokenAmount 703 | | ) internal { 704 | * | if (claimableLongTokenAmount == 0) { 705 | * | fl.log("PositionFees claimableLongTokenAmount is 0"); 706 | | } 707 | * | if (claimableLongTokenAmount > 0 && claimableLongTokenAmount <= 1e6) { 708 | | fl.log( 709 | | "PositionFees claimableLongTokenAmount is between 0 and 1e6" 710 | | ); 711 | | } 712 | * | if ( 713 | * | claimableLongTokenAmount > 1e6 && claimableLongTokenAmount <= 1e12 714 | | ) { 715 | | fl.log( 716 | | "PositionFees claimableLongTokenAmount is between 1e6 and 1e12" 717 | | ); 718 | | } 719 | * | if ( 720 | * | claimableLongTokenAmount > 1e12 && claimableLongTokenAmount <= 1e18 721 | | ) { 722 | | fl.log( 723 | | "PositionFees claimableLongTokenAmount is between 1e12 and 1e18" 724 | | ); 725 | | } 726 | * | if ( 727 | * | claimableLongTokenAmount > 1e18 && claimableLongTokenAmount <= 1e24 728 | | ) { 729 | | fl.log( 730 | | "PositionFees claimableLongTokenAmount is between 1e18 and 1e24" 731 | | ); 732 | | } 733 | * | if (claimableLongTokenAmount > 1e24) { 734 | | fl.log( 735 | | "PositionFees claimableLongTokenAmount is greater than 1e24" 736 | | ); 737 | | } 738 | | } 739 | | 740 | * | function _logPositionFeesClaimableShortTokenAmountCoverage( 741 | | uint256 claimableShortTokenAmount 742 | | ) internal { 743 | * | if (claimableShortTokenAmount == 0) { 744 | * | fl.log("PositionFees claimableShortTokenAmount is 0"); 745 | | } 746 | * | if (claimableShortTokenAmount > 0 && claimableShortTokenAmount <= 1e6) { 747 | | fl.log( 748 | | "PositionFees claimableShortTokenAmount is between 0 and 1e6" 749 | | ); 750 | | } 751 | * | if ( 752 | * | claimableShortTokenAmount > 1e6 && claimableShortTokenAmount <= 1e12 753 | | ) { 754 | * | fl.log( 755 | | "PositionFees claimableShortTokenAmount is between 1e6 and 1e12" 756 | | ); 757 | | } 758 | * | if ( 759 | * | claimableShortTokenAmount > 1e12 && 760 | * | claimableShortTokenAmount <= 1e18 761 | | ) { 762 | * | fl.log( 763 | | "PositionFees claimableShortTokenAmount is between 1e12 and 1e18" 764 | | ); 765 | | } 766 | * | if ( 767 | * | claimableShortTokenAmount > 1e18 && 768 | | claimableShortTokenAmount <= 1e24 769 | | ) { 770 | | fl.log( 771 | | "PositionFees claimableShortTokenAmount is between 1e18 and 1e24" 772 | | ); 773 | | } 774 | * | if (claimableShortTokenAmount > 1e24) { 775 | | fl.log( 776 | | "PositionFees claimableShortTokenAmount is greater than 1e24" 777 | | ); 778 | | } 779 | | } 780 | | 781 | * | function _logPositionFeesLatestFundingFeeAmountPerSizeCoverage( 782 | | uint256 latestFundingFeeAmountPerSize 783 | | ) internal { 784 | * | if (latestFundingFeeAmountPerSize == 0) { 785 | * | fl.log("PositionFees latestFundingFeeAmountPerSize is 0"); 786 | | } 787 | * | if ( 788 | * | latestFundingFeeAmountPerSize > 0 && 789 | * | latestFundingFeeAmountPerSize <= 1e6 790 | | ) { 791 | | fl.log( 792 | | "PositionFees latestFundingFeeAmountPerSize is between 0 and 1e6" 793 | | ); 794 | | } 795 | * | if ( 796 | * | latestFundingFeeAmountPerSize > 1e6 && 797 | * | latestFundingFeeAmountPerSize <= 1e12 798 | | ) { 799 | | fl.log( 800 | | "PositionFees latestFundingFeeAmountPerSize is between 1e6 and 1e12" 801 | | ); 802 | | } 803 | * | if ( 804 | * | latestFundingFeeAmountPerSize > 1e12 && 805 | * | latestFundingFeeAmountPerSize <= 1e18 806 | | ) { 807 | * | fl.log( 808 | | "PositionFees latestFundingFeeAmountPerSize is between 1e12 and 1e18" 809 | | ); 810 | | } 811 | * | if ( 812 | * | latestFundingFeeAmountPerSize > 1e18 && 813 | * | latestFundingFeeAmountPerSize <= 1e24 814 | | ) { 815 | * | fl.log( 816 | | "PositionFees latestFundingFeeAmountPerSize is between 1e18 and 1e24" 817 | | ); 818 | | } 819 | * | if (latestFundingFeeAmountPerSize > 1e24) { 820 | * | fl.log( 821 | | "PositionFees latestFundingFeeAmountPerSize is greater than 1e24" 822 | | ); 823 | | } 824 | | } 825 | | 826 | * | function _logPositionFeesLatestLongTokenClaimableFundingAmountPerSizeCoverage( 827 | | uint256 latestLongTokenClaimableFundingAmountPerSize 828 | | ) internal { 829 | * | if (latestLongTokenClaimableFundingAmountPerSize == 0) { 830 | * | fl.log( 831 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is 0" 832 | | ); 833 | | } 834 | * | if ( 835 | * | latestLongTokenClaimableFundingAmountPerSize > 0 && 836 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e6 837 | | ) { 838 | | fl.log( 839 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 0 and 1e6" 840 | | ); 841 | | } 842 | * | if ( 843 | * | latestLongTokenClaimableFundingAmountPerSize > 1e6 && 844 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e12 845 | | ) { 846 | | fl.log( 847 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 848 | | ); 849 | | } 850 | * | if ( 851 | * | latestLongTokenClaimableFundingAmountPerSize > 1e12 && 852 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e18 853 | | ) { 854 | * | fl.log( 855 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 856 | | ); 857 | | } 858 | * | if ( 859 | * | latestLongTokenClaimableFundingAmountPerSize > 1e18 && 860 | * | latestLongTokenClaimableFundingAmountPerSize <= 1e24 861 | | ) { 862 | * | fl.log( 863 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 864 | | ); 865 | | } 866 | * | if (latestLongTokenClaimableFundingAmountPerSize > 1e24) { 867 | * | fl.log( 868 | | "PositionFees latestLongTokenClaimableFundingAmountPerSize is greater than 1e24" 869 | | ); 870 | | } 871 | | } 872 | | 873 | * | function _logPositionFeesLatestShortTokenClaimableFundingAmountPerSizeCoverage( 874 | | uint256 latestShortTokenClaimableFundingAmountPerSize 875 | | ) internal { 876 | * | if (latestShortTokenClaimableFundingAmountPerSize == 0) { 877 | * | fl.log( 878 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is 0" 879 | | ); 880 | | } 881 | * | if ( 882 | * | latestShortTokenClaimableFundingAmountPerSize > 0 && 883 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e6 884 | | ) { 885 | | fl.log( 886 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 0 and 1e6" 887 | | ); 888 | | } 889 | * | if ( 890 | * | latestShortTokenClaimableFundingAmountPerSize > 1e6 && 891 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e12 892 | | ) { 893 | | fl.log( 894 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e6 and 1e12" 895 | | ); 896 | | } 897 | * | if ( 898 | * | latestShortTokenClaimableFundingAmountPerSize > 1e12 && 899 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e18 900 | | ) { 901 | * | fl.log( 902 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e12 and 1e18" 903 | | ); 904 | | } 905 | * | if ( 906 | * | latestShortTokenClaimableFundingAmountPerSize > 1e18 && 907 | * | latestShortTokenClaimableFundingAmountPerSize <= 1e24 908 | | ) { 909 | * | fl.log( 910 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is between 1e18 and 1e24" 911 | | ); 912 | | } 913 | * | if (latestShortTokenClaimableFundingAmountPerSize > 1e24) { 914 | * | fl.log( 915 | | "PositionFees latestShortTokenClaimableFundingAmountPerSize is greater than 1e24" 916 | | ); 917 | | } 918 | | } 919 | | 920 | * | function _logPositionFeesBorrowingFeeUsdCoverage( 921 | | uint256 borrowingFeeUsd 922 | | ) internal { 923 | * | if (borrowingFeeUsd == 0) { 924 | * | fl.log("PositionFees borrowingFeeUsd is 0"); 925 | | } 926 | * | if (borrowingFeeUsd > 0 && borrowingFeeUsd <= 1e6) { 927 | | fl.log("PositionFees borrowingFeeUsd is between 0 and 1e6"); 928 | | } 929 | * | if (borrowingFeeUsd > 1e6 && borrowingFeeUsd <= 1e12) { 930 | | fl.log("PositionFees borrowingFeeUsd is between 1e6 and 1e12"); 931 | | } 932 | * | if (borrowingFeeUsd > 1e12 && borrowingFeeUsd <= 1e18) { 933 | | fl.log("PositionFees borrowingFeeUsd is between 1e12 and 1e18"); 934 | | } 935 | * | if (borrowingFeeUsd > 1e18 && borrowingFeeUsd <= 1e24) { 936 | | fl.log("PositionFees borrowingFeeUsd is between 1e18 and 1e24"); 937 | | } 938 | * | if (borrowingFeeUsd > 1e24) { 939 | | fl.log("PositionFees borrowingFeeUsd is greater than 1e24"); 940 | | } 941 | | } 942 | | 943 | * | function _logPositionFeesBorrowingFeeAmountCoverage( 944 | | uint256 borrowingFeeAmount 945 | | ) internal { 946 | * | if (borrowingFeeAmount == 0) { 947 | * | fl.log("PositionFees borrowingFeeAmount is 0"); 948 | | } 949 | * | if (borrowingFeeAmount > 0 && borrowingFeeAmount <= 1e6) { 950 | | fl.log("PositionFees borrowingFeeAmount is between 0 and 1e6"); 951 | | } 952 | * | if (borrowingFeeAmount > 1e6 && borrowingFeeAmount <= 1e12) { 953 | | fl.log("PositionFees borrowingFeeAmount is between 1e6 and 1e12"); 954 | | } 955 | * | if (borrowingFeeAmount > 1e12 && borrowingFeeAmount <= 1e18) { 956 | | fl.log("PositionFees borrowingFeeAmount is between 1e12 and 1e18"); 957 | | } 958 | * | if (borrowingFeeAmount > 1e18 && borrowingFeeAmount <= 1e24) { 959 | | fl.log("PositionFees borrowingFeeAmount is between 1e18 and 1e24"); 960 | | } 961 | * | if (borrowingFeeAmount > 1e24) { 962 | | fl.log("PositionFees borrowingFeeAmount is greater than 1e24"); 963 | | } 964 | | } 965 | | 966 | * | function _logPositionFeesBorrowingFeeReceiverFactorCoverage( 967 | | uint256 borrowingFeeReceiverFactor 968 | | ) internal { 969 | * | if (borrowingFeeReceiverFactor == 0) { 970 | * | fl.log("PositionFees borrowingFeeReceiverFactor is 0"); 971 | | } 972 | * | if ( 973 | * | borrowingFeeReceiverFactor > 0 && borrowingFeeReceiverFactor <= 1e6 974 | | ) { 975 | | fl.log( 976 | | "PositionFees borrowingFeeReceiverFactor is between 0 and 1e6" 977 | | ); 978 | | } 979 | * | if ( 980 | * | borrowingFeeReceiverFactor > 1e6 && 981 | | borrowingFeeReceiverFactor <= 1e12 982 | | ) { 983 | | fl.log( 984 | | "PositionFees borrowingFeeReceiverFactor is between 1e6 and 1e12" 985 | | ); 986 | | } 987 | * | if ( 988 | * | borrowingFeeReceiverFactor > 1e12 && 989 | | borrowingFeeReceiverFactor <= 1e18 990 | | ) { 991 | | fl.log( 992 | | "PositionFees borrowingFeeReceiverFactor is between 1e12 and 1e18" 993 | | ); 994 | | } 995 | * | if ( 996 | * | borrowingFeeReceiverFactor > 1e18 && 997 | | borrowingFeeReceiverFactor <= 1e24 998 | | ) { 999 | | fl.log( 1000 | | "PositionFees borrowingFeeReceiverFactor is between 1e18 and 1e24" 1001 | | ); 1002 | | } 1003 | * | if (borrowingFeeReceiverFactor > 1e24) { 1004 | | fl.log( 1005 | | "PositionFees borrowingFeeReceiverFactor is greater than 1e24" 1006 | | ); 1007 | | } 1008 | | } 1009 | | 1010 | * | function _logPositionFeesBorrowingFeeAmountForFeeReceiverCoverage( 1011 | | uint256 borrowingFeeAmountForFeeReceiver 1012 | | ) internal { 1013 | * | if (borrowingFeeAmountForFeeReceiver == 0) { 1014 | * | fl.log("PositionFees borrowingFeeAmountForFeeReceiver is 0"); 1015 | | } 1016 | * | if ( 1017 | * | borrowingFeeAmountForFeeReceiver > 0 && 1018 | | borrowingFeeAmountForFeeReceiver <= 1e6 1019 | | ) { 1020 | | fl.log( 1021 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 0 and 1e6" 1022 | | ); 1023 | | } 1024 | * | if ( 1025 | * | borrowingFeeAmountForFeeReceiver > 1e6 && 1026 | | borrowingFeeAmountForFeeReceiver <= 1e12 1027 | | ) { 1028 | | fl.log( 1029 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e6 and 1e12" 1030 | | ); 1031 | | } 1032 | * | if ( 1033 | * | borrowingFeeAmountForFeeReceiver > 1e12 && 1034 | | borrowingFeeAmountForFeeReceiver <= 1e18 1035 | | ) { 1036 | | fl.log( 1037 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e12 and 1e18" 1038 | | ); 1039 | | } 1040 | * | if ( 1041 | * | borrowingFeeAmountForFeeReceiver > 1e18 && 1042 | | borrowingFeeAmountForFeeReceiver <= 1e24 1043 | | ) { 1044 | | fl.log( 1045 | | "PositionFees borrowingFeeAmountForFeeReceiver is between 1e18 and 1e24" 1046 | | ); 1047 | | } 1048 | * | if (borrowingFeeAmountForFeeReceiver > 1e24) { 1049 | | fl.log( 1050 | | "PositionFees borrowingFeeAmountForFeeReceiver is greater than 1e24" 1051 | | ); 1052 | | } 1053 | | } 1054 | | 1055 | * | function _logPositionFeesUiFeeReceiverCoverage( 1056 | | address uiFeeReceiver 1057 | | ) internal { 1058 | * | if (uiFeeReceiver == address(0)) { 1059 | * | fl.log("PositionFees uiFeeReceiver is address(0)"); 1060 | | } else { 1061 | | fl.log("PositionFees uiFeeReceiver is non-zero address"); 1062 | | } 1063 | | } 1064 | | 1065 | * | function _logPositionFeesUiFeeReceiverFactorCoverage( 1066 | | uint256 uiFeeReceiverFactor 1067 | | ) internal { 1068 | * | if (uiFeeReceiverFactor == 0) { 1069 | * | fl.log("PositionFees uiFeeReceiverFactor is 0"); 1070 | | } 1071 | * | if (uiFeeReceiverFactor > 0 && uiFeeReceiverFactor <= 1e6) { 1072 | | fl.log("PositionFees uiFeeReceiverFactor is between 0 and 1e6"); 1073 | | } 1074 | * | if (uiFeeReceiverFactor > 1e6 && uiFeeReceiverFactor <= 1e12) { 1075 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e6 and 1e12"); 1076 | | } 1077 | * | if (uiFeeReceiverFactor > 1e12 && uiFeeReceiverFactor <= 1e18) { 1078 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e12 and 1e18"); 1079 | | } 1080 | * | if (uiFeeReceiverFactor > 1e18 && uiFeeReceiverFactor <= 1e24) { 1081 | | fl.log("PositionFees uiFeeReceiverFactor is between 1e18 and 1e24"); 1082 | | } 1083 | * | if (uiFeeReceiverFactor > 1e24) { 1084 | | fl.log("PositionFees uiFeeReceiverFactor is greater than 1e24"); 1085 | | } 1086 | | } 1087 | | 1088 | * | function _logPositionFeesUiFeeAmountCoverage(uint256 uiFeeAmount) internal { 1089 | * | if (uiFeeAmount == 0) { 1090 | * | fl.log("PositionFees uiFeeAmount is 0"); 1091 | | } 1092 | * | if (uiFeeAmount > 0 && uiFeeAmount <= 1e6) { 1093 | | fl.log("PositionFees uiFeeAmount is between 0 and 1e6"); 1094 | | } 1095 | * | if (uiFeeAmount > 1e6 && uiFeeAmount <= 1e12) { 1096 | | fl.log("PositionFees uiFeeAmount is between 1e6 and 1e12"); 1097 | | } 1098 | * | if (uiFeeAmount > 1e12 && uiFeeAmount <= 1e18) { 1099 | | fl.log("PositionFees uiFeeAmount is between 1e12 and 1e18"); 1100 | | } 1101 | * | if (uiFeeAmount > 1e18 && uiFeeAmount <= 1e24) { 1102 | | fl.log("PositionFees uiFeeAmount is between 1e18 and 1e24"); 1103 | | } 1104 | * | if (uiFeeAmount > 1e24) { 1105 | | fl.log("PositionFees uiFeeAmount is greater than 1e24"); 1106 | | } 1107 | | } 1108 | | 1109 | * | function _logPositionFeesCollateralTokenPriceCoverage( 1110 | | uint256 collateralTokenPrice 1111 | | ) internal { 1112 | * | if (collateralTokenPrice == 0) { 1113 | | fl.log("PositionFees collateralTokenPrice is 0"); 1114 | | } 1115 | * | if (collateralTokenPrice > 0 && collateralTokenPrice <= 1e6) { 1116 | | fl.log("PositionFees collateralTokenPrice is between 0 and 1e6"); 1117 | | } 1118 | * | if (collateralTokenPrice > 1e6 && collateralTokenPrice <= 1e12) { 1119 | | fl.log("PositionFees collateralTokenPrice is between 1e6 and 1e12"); 1120 | | } 1121 | * | if (collateralTokenPrice > 1e12 && collateralTokenPrice <= 1e18) { 1122 | * | fl.log( 1123 | | "PositionFees collateralTokenPrice is between 1e12 and 1e18" 1124 | | ); 1125 | | } 1126 | * | if (collateralTokenPrice > 1e18 && collateralTokenPrice <= 1e24) { 1127 | * | fl.log( 1128 | | "PositionFees collateralTokenPrice is between 1e18 and 1e24" 1129 | | ); 1130 | | } 1131 | * | if (collateralTokenPrice > 1e24) { 1132 | * | fl.log("PositionFees collateralTokenPrice is greater than 1e24"); 1133 | | } 1134 | | } 1135 | | 1136 | * | function _logPositionFeesPositionFeeFactorCoverage( 1137 | | uint256 positionFeeFactor 1138 | | ) internal { 1139 | * | if (positionFeeFactor == 0) { 1140 | * | fl.log("PositionFees positionFeeFactor is 0"); 1141 | | } 1142 | * | if (positionFeeFactor > 0 && positionFeeFactor <= 1e6) { 1143 | | fl.log("PositionFees positionFeeFactor is between 0 and 1e6"); 1144 | | } 1145 | * | if (positionFeeFactor > 1e6 && positionFeeFactor <= 1e12) { 1146 | | fl.log("PositionFees positionFeeFactor is between 1e6 and 1e12"); 1147 | | } 1148 | * | if (positionFeeFactor > 1e12 && positionFeeFactor <= 1e18) { 1149 | | fl.log("PositionFees positionFeeFactor is between 1e12 and 1e18"); 1150 | | } 1151 | * | if (positionFeeFactor > 1e18 && positionFeeFactor <= 1e24) { 1152 | | fl.log("PositionFees positionFeeFactor is between 1e18 and 1e24"); 1153 | | } 1154 | * | if (positionFeeFactor > 1e24) { 1155 | | fl.log("PositionFees positionFeeFactor is greater than 1e24"); 1156 | | } 1157 | | } 1158 | | 1159 | * | function _logPositionFeesProtocolFeeAmountCoverage( 1160 | | uint256 protocolFeeAmount 1161 | | ) internal { 1162 | * | if (protocolFeeAmount == 0) { 1163 | * | fl.log("PositionFees protocolFeeAmount is 0"); 1164 | | } 1165 | * | if (protocolFeeAmount > 0 && protocolFeeAmount <= 1e6) { 1166 | | fl.log("PositionFees protocolFeeAmount is between 0 and 1e6"); 1167 | | } 1168 | * | if (protocolFeeAmount > 1e6 && protocolFeeAmount <= 1e12) { 1169 | | fl.log("PositionFees protocolFeeAmount is between 1e6 and 1e12"); 1170 | | } 1171 | * | if (protocolFeeAmount > 1e12 && protocolFeeAmount <= 1e18) { 1172 | | fl.log("PositionFees protocolFeeAmount is between 1e12 and 1e18"); 1173 | | } 1174 | * | if (protocolFeeAmount > 1e18 && protocolFeeAmount <= 1e24) { 1175 | | fl.log("PositionFees protocolFeeAmount is between 1e18 and 1e24"); 1176 | | } 1177 | * | if (protocolFeeAmount > 1e24) { 1178 | | fl.log("PositionFees protocolFeeAmount is greater than 1e24"); 1179 | | } 1180 | | } 1181 | | 1182 | * | function _logPositionFeesPositionFeeReceiverFactorCoverage( 1183 | | uint256 positionFeeReceiverFactor 1184 | | ) internal { 1185 | * | if (positionFeeReceiverFactor == 0) { 1186 | * | fl.log("PositionFees positionFeeReceiverFactor is 0"); 1187 | | } 1188 | * | if (positionFeeReceiverFactor > 0 && positionFeeReceiverFactor <= 1e6) { 1189 | | fl.log( 1190 | | "PositionFees positionFeeReceiverFactor is between 0 and 1e6" 1191 | | ); 1192 | | } 1193 | * | if ( 1194 | * | positionFeeReceiverFactor > 1e6 && positionFeeReceiverFactor <= 1e12 1195 | | ) { 1196 | | fl.log( 1197 | | "PositionFees positionFeeReceiverFactor is between 1e6 and 1e12" 1198 | | ); 1199 | | } 1200 | * | if ( 1201 | * | positionFeeReceiverFactor > 1e12 && 1202 | | positionFeeReceiverFactor <= 1e18 1203 | | ) { 1204 | | fl.log( 1205 | | "PositionFees positionFeeReceiverFactor is between 1e12 and 1e18" 1206 | | ); 1207 | | } 1208 | * | if ( 1209 | * | positionFeeReceiverFactor > 1e18 && 1210 | | positionFeeReceiverFactor <= 1e24 1211 | | ) { 1212 | | fl.log( 1213 | | "PositionFees positionFeeReceiverFactor is between 1e18 and 1e24" 1214 | | ); 1215 | | } 1216 | * | if (positionFeeReceiverFactor > 1e24) { 1217 | | fl.log( 1218 | | "PositionFees positionFeeReceiverFactor is greater than 1e24" 1219 | | ); 1220 | | } 1221 | | } 1222 | | 1223 | * | function _logPositionFeesFeeReceiverAmountCoverage( 1224 | | uint256 feeReceiverAmount 1225 | | ) internal { 1226 | * | if (feeReceiverAmount == 0) { 1227 | * | fl.log("PositionFees feeReceiverAmount is 0"); 1228 | | } 1229 | * | if (feeReceiverAmount > 0 && feeReceiverAmount <= 1e6) { 1230 | | fl.log("PositionFees feeReceiverAmount is between 0 and 1e6"); 1231 | | } 1232 | * | if (feeReceiverAmount > 1e6 && feeReceiverAmount <= 1e12) { 1233 | | fl.log("PositionFees feeReceiverAmount is between 1e6 and 1e12"); 1234 | | } 1235 | * | if (feeReceiverAmount > 1e12 && feeReceiverAmount <= 1e18) { 1236 | | fl.log("PositionFees feeReceiverAmount is between 1e12 and 1e18"); 1237 | | } 1238 | * | if (feeReceiverAmount > 1e18 && feeReceiverAmount <= 1e24) { 1239 | | fl.log("PositionFees feeReceiverAmount is between 1e18 and 1e24"); 1240 | | } 1241 | * | if (feeReceiverAmount > 1e24) { 1242 | | fl.log("PositionFees feeReceiverAmount is greater than 1e24"); 1243 | | } 1244 | | } 1245 | | 1246 | * | function _logPositionFeesFeeAmountForPoolCoverage( 1247 | | uint256 feeAmountForPool 1248 | | ) internal { 1249 | * | if (feeAmountForPool == 0) { 1250 | * | fl.log("PositionFees feeAmountForPool is 0"); 1251 | | } 1252 | * | if (feeAmountForPool > 0 && feeAmountForPool <= 1e6) { 1253 | | fl.log("PositionFees feeAmountForPool is between 0 and 1e6"); 1254 | | } 1255 | * | if (feeAmountForPool > 1e6 && feeAmountForPool <= 1e12) { 1256 | | fl.log("PositionFees feeAmountForPool is between 1e6 and 1e12"); 1257 | | } 1258 | * | if (feeAmountForPool > 1e12 && feeAmountForPool <= 1e18) { 1259 | | fl.log("PositionFees feeAmountForPool is between 1e12 and 1e18"); 1260 | | } 1261 | * | if (feeAmountForPool > 1e18 && feeAmountForPool <= 1e24) { 1262 | | fl.log("PositionFees feeAmountForPool is between 1e18 and 1e24"); 1263 | | } 1264 | * | if (feeAmountForPool > 1e24) { 1265 | | fl.log("PositionFees feeAmountForPool is greater than 1e24"); 1266 | | } 1267 | | } 1268 | | 1269 | * | function _logPositionFeesPositionFeeAmountForPoolCoverage( 1270 | | uint256 positionFeeAmountForPool 1271 | | ) internal { 1272 | * | if (positionFeeAmountForPool == 0) { 1273 | * | fl.log("PositionFees positionFeeAmountForPool is 0"); 1274 | | } 1275 | * | if (positionFeeAmountForPool > 0 && positionFeeAmountForPool <= 1e6) { 1276 | | fl.log( 1277 | | "PositionFees positionFeeAmountForPool is between 0 and 1e6" 1278 | | ); 1279 | | } 1280 | * | if ( 1281 | * | positionFeeAmountForPool > 1e6 && positionFeeAmountForPool <= 1e12 1282 | | ) { 1283 | | fl.log( 1284 | | "PositionFees positionFeeAmountForPool is between 1e6 and 1e12" 1285 | | ); 1286 | | } 1287 | * | if ( 1288 | * | positionFeeAmountForPool > 1e12 && positionFeeAmountForPool <= 1e18 1289 | | ) { 1290 | | fl.log( 1291 | | "PositionFees positionFeeAmountForPool is between 1e12 and 1e18" 1292 | | ); 1293 | | } 1294 | * | if ( 1295 | * | positionFeeAmountForPool > 1e18 && positionFeeAmountForPool <= 1e24 1296 | | ) { 1297 | | fl.log( 1298 | | "PositionFees positionFeeAmountForPool is between 1e18 and 1e24" 1299 | | ); 1300 | | } 1301 | * | if (positionFeeAmountForPool > 1e24) { 1302 | | fl.log( 1303 | | "PositionFees positionFeeAmountForPool is greater than 1e24" 1304 | | ); 1305 | | } 1306 | | } 1307 | | 1308 | * | function _logPositionFeesPositionFeeAmountCoverage( 1309 | | uint256 positionFeeAmount 1310 | | ) internal { 1311 | * | if (positionFeeAmount == 0) { 1312 | * | fl.log("PositionFees positionFeeAmount is 0"); 1313 | | } 1314 | * | if (positionFeeAmount > 0 && positionFeeAmount <= 1e6) { 1315 | | fl.log("PositionFees positionFeeAmount is between 0 and 1e6"); 1316 | | } 1317 | * | if (positionFeeAmount > 1e6 && positionFeeAmount <= 1e12) { 1318 | | fl.log("PositionFees positionFeeAmount is between 1e6 and 1e12"); 1319 | | } 1320 | * | if (positionFeeAmount > 1e12 && positionFeeAmount <= 1e18) { 1321 | | fl.log("PositionFees positionFeeAmount is between 1e12 and 1e18"); 1322 | | } 1323 | * | if (positionFeeAmount > 1e18 && positionFeeAmount <= 1e24) { 1324 | | fl.log("PositionFees positionFeeAmount is between 1e18 and 1e24"); 1325 | | } 1326 | * | if (positionFeeAmount > 1e24) { 1327 | | fl.log("PositionFees positionFeeAmount is greater than 1e24"); 1328 | | } 1329 | | } 1330 | | 1331 | * | function _logPositionFeesTotalCostAmountExcludingFundingCoverage( 1332 | | uint256 totalCostAmountExcludingFunding 1333 | | ) internal { 1334 | * | if (totalCostAmountExcludingFunding == 0) { 1335 | * | fl.log("PositionFees totalCostAmountExcludingFunding is 0"); 1336 | | } 1337 | * | if ( 1338 | * | totalCostAmountExcludingFunding > 0 && 1339 | | totalCostAmountExcludingFunding <= 1e6 1340 | | ) { 1341 | | fl.log( 1342 | | "PositionFees totalCostAmountExcludingFunding is between 0 and 1e6" 1343 | | ); 1344 | | } 1345 | * | if ( 1346 | * | totalCostAmountExcludingFunding > 1e6 && 1347 | | totalCostAmountExcludingFunding <= 1e12 1348 | | ) { 1349 | | fl.log( 1350 | | "PositionFees totalCostAmountExcludingFunding is between 1e6 and 1e12" 1351 | | ); 1352 | | } 1353 | * | if ( 1354 | * | totalCostAmountExcludingFunding > 1e12 && 1355 | | totalCostAmountExcludingFunding <= 1e18 1356 | | ) { 1357 | | fl.log( 1358 | | "PositionFees totalCostAmountExcludingFunding is between 1e12 and 1e18" 1359 | | ); 1360 | | } 1361 | * | if ( 1362 | * | totalCostAmountExcludingFunding > 1e18 && 1363 | | totalCostAmountExcludingFunding <= 1e24 1364 | | ) { 1365 | | fl.log( 1366 | | "PositionFees totalCostAmountExcludingFunding is between 1e18 and 1e24" 1367 | | ); 1368 | | } 1369 | * | if (totalCostAmountExcludingFunding > 1e24) { 1370 | | fl.log( 1371 | | "PositionFees totalCostAmountExcludingFunding is greater than 1e24" 1372 | | ); 1373 | | } 1374 | | } 1375 | | 1376 | * | function _logPositionFeesTotalCostAmountCoverage( 1377 | | uint256 totalCostAmount 1378 | | ) internal { 1379 | * | if (totalCostAmount == 0) { 1380 | * | fl.log("PositionFees totalCostAmount is 0"); 1381 | | } 1382 | * | if (totalCostAmount > 0 && totalCostAmount <= 1e6) { 1383 | * | fl.log("PositionFees totalCostAmount is between 0 and 1e6"); 1384 | | } 1385 | * | if (totalCostAmount > 1e6 && totalCostAmount <= 1e12) { 1386 | * | fl.log("PositionFees totalCostAmount is between 1e6 and 1e12"); 1387 | | } 1388 | * | if (totalCostAmount > 1e12 && totalCostAmount <= 1e18) { 1389 | * | fl.log("PositionFees totalCostAmount is between 1e12 and 1e18"); 1390 | | } 1391 | * | if (totalCostAmount > 1e18 && totalCostAmount <= 1e24) { 1392 | * | fl.log("PositionFees totalCostAmount is between 1e18 and 1e24"); 1393 | | } 1394 | * | if (totalCostAmount > 1e24) { 1395 | | fl.log("PositionFees totalCostAmount is greater than 1e24"); 1396 | | } 1397 | | } 1398 | | 1399 | * | function _logExecutionPriceResultPriceImpactUsdCoverage( 1400 | | int256 priceImpactUsd 1401 | | ) internal { 1402 | * | if (priceImpactUsd == 0) { 1403 | * | fl.log("ExecutionPriceResult priceImpactUsd is 0"); 1404 | | } 1405 | * | if (priceImpactUsd > 0 && priceImpactUsd <= 1e6) { 1406 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and 1e6"); 1407 | | } 1408 | * | if (priceImpactUsd > 1e6 && priceImpactUsd <= 1e12) { 1409 | | fl.log( 1410 | | "ExecutionPriceResult priceImpactUsd is between 1e6 and 1e12" 1411 | | ); 1412 | | } 1413 | * | if (priceImpactUsd > 1e12 && priceImpactUsd <= 1e18) { 1414 | | fl.log( 1415 | | "ExecutionPriceResult priceImpactUsd is between 1e12 and 1e18" 1416 | | ); 1417 | | } 1418 | * | if (priceImpactUsd > 1e18 && priceImpactUsd <= 1e24) { 1419 | | fl.log( 1420 | | "ExecutionPriceResult priceImpactUsd is between 1e18 and 1e24" 1421 | | ); 1422 | | } 1423 | * | if (priceImpactUsd > 1e24) { 1424 | | fl.log("ExecutionPriceResult priceImpactUsd is greater than 1e24"); 1425 | | } 1426 | * | if (priceImpactUsd < 0 && priceImpactUsd >= -1e6) { 1427 | | fl.log("ExecutionPriceResult priceImpactUsd is between 0 and -1e6"); 1428 | | } 1429 | * | if (priceImpactUsd < -1e6 && priceImpactUsd >= -1e12) { 1430 | | fl.log( 1431 | | "ExecutionPriceResult priceImpactUsd is between -1e6 and -1e12" 1432 | | ); 1433 | | } 1434 | * | if (priceImpactUsd < -1e12 && priceImpactUsd >= -1e18) { 1435 | | fl.log( 1436 | | "ExecutionPriceResult priceImpactUsd is between -1e12 and -1e18" 1437 | | ); 1438 | | } 1439 | * | if (priceImpactUsd < -1e18 && priceImpactUsd >= -1e24) { 1440 | | fl.log( 1441 | | "ExecutionPriceResult priceImpactUsd is between -1e18 and -1e24" 1442 | | ); 1443 | | } 1444 | * | if (priceImpactUsd < -1e24) { 1445 | | fl.log("ExecutionPriceResult priceImpactUsd is less than -1e24"); 1446 | | } 1447 | | } 1448 | * | function _logExecutionPriceResultPriceImpactDiffUsdCoverage( 1449 | | uint256 priceImpactDiffUsd 1450 | | ) internal { 1451 | * | if (priceImpactDiffUsd == 0) { 1452 | * | fl.log("ExecutionPriceResult priceImpactDiffUsd is 0"); 1453 | | } 1454 | * | if (priceImpactDiffUsd > 0 && priceImpactDiffUsd <= 1e6) { 1455 | | fl.log( 1456 | | "ExecutionPriceResult priceImpactDiffUsd is between 0 and 1e6" 1457 | | ); 1458 | | } 1459 | * | if (priceImpactDiffUsd > 1e6 && priceImpactDiffUsd <= 1e12) { 1460 | | fl.log( 1461 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e6 and 1e12" 1462 | | ); 1463 | | } 1464 | * | if (priceImpactDiffUsd > 1e12 && priceImpactDiffUsd <= 1e18) { 1465 | | fl.log( 1466 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e12 and 1e18" 1467 | | ); 1468 | | } 1469 | * | if (priceImpactDiffUsd > 1e18 && priceImpactDiffUsd <= 1e24) { 1470 | | fl.log( 1471 | | "ExecutionPriceResult priceImpactDiffUsd is between 1e18 and 1e24" 1472 | | ); 1473 | | } 1474 | * | if (priceImpactDiffUsd > 1e24) { 1475 | | fl.log( 1476 | | "ExecutionPriceResult priceImpactDiffUsd is greater than 1e24" 1477 | | ); 1478 | | } 1479 | | } 1480 | * | function _logExecutionPriceResultExecutionPriceCoverage( 1481 | | uint256 executionPrice 1482 | | ) internal { 1483 | * | if (executionPrice == 0) { 1484 | | fl.log("ExecutionPriceResult executionPrice is 0"); 1485 | | } 1486 | * | if (executionPrice > 0 && executionPrice <= 1e6) { 1487 | | fl.log("ExecutionPriceResult executionPrice is between 0 and 1e6"); 1488 | | } 1489 | * | if (executionPrice > 1e6 && executionPrice <= 1e12) { 1490 | | fl.log( 1491 | | "ExecutionPriceResult executionPrice is between 1e6 and 1e12" 1492 | | ); 1493 | | } 1494 | * | if (executionPrice > 1e12 && executionPrice <= 1e18) { 1495 | * | fl.log( 1496 | | "ExecutionPriceResult executionPrice is between 1e12 and 1e18" 1497 | | ); 1498 | | } 1499 | * | if (executionPrice > 1e18 && executionPrice <= 1e24) { 1500 | | fl.log( 1501 | | "ExecutionPriceResult executionPrice is between 1e18 and 1e24" 1502 | | ); 1503 | | } 1504 | * | if (executionPrice > 1e24) { 1505 | * | fl.log("ExecutionPriceResult executionPrice is greater than 1e24"); 1506 | | } 1507 | | } 1508 | * | function _logPositionInfoBasePnlUsdCoverage(int256 basePnlUsd) internal { 1509 | * | if (basePnlUsd == 0) { 1510 | * | fl.log("PositionInfo basePnlUsd is 0"); 1511 | | } 1512 | * | if (basePnlUsd > 0 && basePnlUsd <= 1e6) { 1513 | | fl.log("PositionInfo basePnlUsd is between 0 and 1e6"); 1514 | | } 1515 | * | if (basePnlUsd > 1e6 && basePnlUsd <= 1e12) { 1516 | | fl.log("PositionInfo basePnlUsd is between 1e6 and 1e12"); 1517 | | } 1518 | * | if (basePnlUsd > 1e12 && basePnlUsd <= 1e18) { 1519 | | fl.log("PositionInfo basePnlUsd is between 1e12 and 1e18"); 1520 | | } 1521 | * | if (basePnlUsd > 1e18 && basePnlUsd <= 1e24) { 1522 | | fl.log("PositionInfo basePnlUsd is between 1e18 and 1e24"); 1523 | | } 1524 | * | if (basePnlUsd > 1e24) { 1525 | * | fl.log("PositionInfo basePnlUsd is greater than 1e24"); 1526 | | } 1527 | * | if (basePnlUsd < 0 && basePnlUsd >= -1e6) { 1528 | | fl.log("PositionInfo basePnlUsd is between 0 and -1e6"); 1529 | | } 1530 | * | if (basePnlUsd < -1e6 && basePnlUsd >= -1e12) { 1531 | | fl.log("PositionInfo basePnlUsd is between -1e6 and -1e12"); 1532 | | } 1533 | * | if (basePnlUsd < -1e12 && basePnlUsd >= -1e18) { 1534 | * | fl.log("PositionInfo basePnlUsd is between -1e12 and -1e18"); 1535 | | } 1536 | * | if (basePnlUsd < -1e18 && basePnlUsd >= -1e24) { 1537 | * | fl.log("PositionInfo basePnlUsd is between -1e18 and -1e24"); 1538 | | } 1539 | * | if (basePnlUsd < -1e24) { 1540 | * | fl.log("PositionInfo basePnlUsd is less than -1e24"); 1541 | | } 1542 | | } 1543 | * | function _logPositionInfoUncappedBasePnlUsdCoverage( 1544 | | int256 uncappedBasePnlUsd 1545 | | ) internal { 1546 | * | if (uncappedBasePnlUsd == 0) { 1547 | * | fl.log("PositionInfo uncappedBasePnlUsd is 0"); 1548 | | } 1549 | * | if (uncappedBasePnlUsd > 0 && uncappedBasePnlUsd <= 1e6) { 1550 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and 1e6"); 1551 | | } 1552 | * | if (uncappedBasePnlUsd > 1e6 && uncappedBasePnlUsd <= 1e12) { 1553 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e6 and 1e12"); 1554 | | } 1555 | * | if (uncappedBasePnlUsd > 1e12 && uncappedBasePnlUsd <= 1e18) { 1556 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e12 and 1e18"); 1557 | | } 1558 | * | if (uncappedBasePnlUsd > 1e18 && uncappedBasePnlUsd <= 1e24) { 1559 | | fl.log("PositionInfo uncappedBasePnlUsd is between 1e18 and 1e24"); 1560 | | } 1561 | * | if (uncappedBasePnlUsd > 1e24) { 1562 | * | fl.log("PositionInfo uncappedBasePnlUsd is greater than 1e24"); 1563 | | } 1564 | * | if (uncappedBasePnlUsd < 0 && uncappedBasePnlUsd >= -1e6) { 1565 | | fl.log("PositionInfo uncappedBasePnlUsd is between 0 and -1e6"); 1566 | | } 1567 | * | if (uncappedBasePnlUsd < -1e6 && uncappedBasePnlUsd >= -1e12) { 1568 | | fl.log("PositionInfo uncappedBasePnlUsd is between -1e6 and -1e12"); 1569 | | } 1570 | * | if (uncappedBasePnlUsd < -1e12 && uncappedBasePnlUsd >= -1e18) { 1571 | * | fl.log( 1572 | | "PositionInfo uncappedBasePnlUsd is between -1e12 and -1e18" 1573 | | ); 1574 | | } 1575 | * | if (uncappedBasePnlUsd < -1e18 && uncappedBasePnlUsd >= -1e24) { 1576 | * | fl.log( 1577 | | "PositionInfo uncappedBasePnlUsd is between -1e18 and -1e24" 1578 | | ); 1579 | | } 1580 | * | if (uncappedBasePnlUsd < -1e24) { 1581 | * | fl.log("PositionInfo uncappedBasePnlUsd is less than -1e24"); 1582 | | } 1583 | | } 1584 | * | function _logPositionInfoPnlAfterPriceImpactUsdCoverage( 1585 | | int256 pnlAfterPriceImpactUsd 1586 | | ) internal { 1587 | * | if (pnlAfterPriceImpactUsd == 0) { 1588 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is 0"); 1589 | | } 1590 | * | if (pnlAfterPriceImpactUsd > 0 && pnlAfterPriceImpactUsd <= 1e6) { 1591 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and 1e6"); 1592 | | } 1593 | * | if (pnlAfterPriceImpactUsd > 1e6 && pnlAfterPriceImpactUsd <= 1e12) { 1594 | | fl.log( 1595 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e6 and 1e12" 1596 | | ); 1597 | | } 1598 | * | if (pnlAfterPriceImpactUsd > 1e12 && pnlAfterPriceImpactUsd <= 1e18) { 1599 | | fl.log( 1600 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e12 and 1e18" 1601 | | ); 1602 | | } 1603 | * | if (pnlAfterPriceImpactUsd > 1e18 && pnlAfterPriceImpactUsd <= 1e24) { 1604 | | fl.log( 1605 | | "PositionInfo pnlAfterPriceImpactUsd is between 1e18 and 1e24" 1606 | | ); 1607 | | } 1608 | * | if (pnlAfterPriceImpactUsd > 1e24) { 1609 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is greater than 1e24"); 1610 | | } 1611 | * | if (pnlAfterPriceImpactUsd < 0 && pnlAfterPriceImpactUsd >= -1e6) { 1612 | | fl.log("PositionInfo pnlAfterPriceImpactUsd is between 0 and -1e6"); 1613 | | } 1614 | * | if (pnlAfterPriceImpactUsd < -1e6 && pnlAfterPriceImpactUsd >= -1e12) { 1615 | | fl.log( 1616 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e6 and -1e12" 1617 | | ); 1618 | | } 1619 | * | if (pnlAfterPriceImpactUsd < -1e12 && pnlAfterPriceImpactUsd >= -1e18) { 1620 | * | fl.log( 1621 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e12 and -1e18" 1622 | | ); 1623 | | } 1624 | * | if (pnlAfterPriceImpactUsd < -1e18 && pnlAfterPriceImpactUsd >= -1e24) { 1625 | * | fl.log( 1626 | | "PositionInfo pnlAfterPriceImpactUsd is between -1e18 and -1e24" 1627 | | ); 1628 | | } 1629 | * | if (pnlAfterPriceImpactUsd < -1e24) { 1630 | * | fl.log("PositionInfo pnlAfterPriceImpactUsd is less than -1e24"); 1631 | | } 1632 | | } 1633 | | } 1634 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/positionCoverage/IncreasePositionMarketCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract IncreasePositionMarketCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ INCREASE POSITION 10 | | // __^ __( \.__) ) GET MARKET INFO 11 | | // (@)<_____>__(_____)____/ COVERAGE 12 | | 13 | * | function _checkIncreaseOrderAndGetMarketInfoCoverage( 14 | | ReaderUtils.MarketInfo memory marketInfo 15 | | ) internal { 16 | * | _logMarketInfoMarketTokenCoverage(marketInfo.market.marketToken); 17 | * | _logMarketInfoIndexTokenCoverage(marketInfo.market.indexToken); 18 | * | _logMarketInfoLongTokenCoverage(marketInfo.market.longToken); 19 | * | _logMarketInfoShortTokenCoverage(marketInfo.market.shortToken); 20 | * | _logMarketInfoBorrowingFactorPerSecondForLongsCoverage( 21 | * | marketInfo.borrowingFactorPerSecondForLongs 22 | | ); 23 | * | _logMarketInfoBorrowingFactorPerSecondForShortsCoverage( 24 | * | marketInfo.borrowingFactorPerSecondForShorts 25 | | ); 26 | * | _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage( 27 | * | marketInfo.baseFunding.fundingFeeAmountPerSize.long 28 | | ); 29 | * | _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage( 30 | * | marketInfo.baseFunding.fundingFeeAmountPerSize.short 31 | | ); 32 | * | _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage( 33 | * | marketInfo.baseFunding.claimableFundingAmountPerSize.long 34 | | ); 35 | * | _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage( 36 | * | marketInfo.baseFunding.claimableFundingAmountPerSize.short 37 | | ); 38 | * | _logMarketInfoNextFundingLongsPayShortsCoverage( 39 | * | marketInfo.nextFunding.longsPayShorts 40 | | ); 41 | * | _logMarketInfoNextFundingFundingFactorPerSecondCoverage( 42 | * | marketInfo.nextFunding.fundingFactorPerSecond 43 | | ); 44 | * | _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage( 45 | * | marketInfo.nextFunding.nextSavedFundingFactorPerSecond 46 | | ); 47 | * | _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage( 48 | * | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.long 49 | | ); 50 | * | _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage( 51 | * | marketInfo.nextFunding.fundingFeeAmountPerSizeDelta.short 52 | | ); 53 | * | _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage( 54 | * | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.long 55 | | ); 56 | * | _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage( 57 | * | marketInfo.nextFunding.claimableFundingAmountPerSizeDelta.short 58 | | ); 59 | * | _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage( 60 | * | marketInfo.virtualInventory.virtualPoolAmountForLongToken 61 | | ); 62 | * | _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage( 63 | * | marketInfo.virtualInventory.virtualPoolAmountForShortToken 64 | | ); 65 | * | _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage( 66 | * | marketInfo.virtualInventory.virtualInventoryForPositions 67 | | ); 68 | * | _logMarketInfoIsDisabledCoverage(marketInfo.isDisabled); 69 | | } 70 | | 71 | * | function _logMarketInfoMarketTokenCoverage(address marketToken) internal { 72 | * | if (marketToken == address(market_0_WETH_USDC)) { 73 | | fl.log("MarketInfo marketToken market_0_WETH_USDC hit"); 74 | | } 75 | | 76 | * | if (marketToken == address(market_WBTC_WBTC_USDC)) { 77 | * | fl.log("MarketInfo marketToken market_WBTC_WBTC_USDC hit"); 78 | | } 79 | * | if (marketToken == address(market_WETH_WETH_USDC)) { 80 | * | fl.log("MarketInfo marketToken market_WETH_WETH_USDC hit"); 81 | | } 82 | * | if (marketToken == address(market_WETH_WETH_USDT)) { 83 | * | fl.log("MarketInfo marketToken market_WETH_WETH_USDT hit"); 84 | | } 85 | | } 86 | | 87 | * | function _logMarketInfoIndexTokenCoverage(address indexToken) internal { 88 | * | if (indexToken == address(0)) { 89 | | fl.log("MarketInfo indexToken is address(0)"); 90 | | } else { 91 | * | fl.log("MarketInfo indexToken is non-zero address"); 92 | | } 93 | | } 94 | | 95 | * | function _logMarketInfoLongTokenCoverage(address longToken) internal { 96 | * | if (longToken == address(0)) { 97 | | fl.log("MarketInfo longToken is address(0)"); 98 | | } else { 99 | * | fl.log("MarketInfo longToken is non-zero address"); 100 | | } 101 | | } 102 | | 103 | * | function _logMarketInfoShortTokenCoverage(address shortToken) internal { 104 | * | if (shortToken == address(0)) { 105 | | fl.log("MarketInfo shortToken is address(0)"); 106 | | } else { 107 | * | fl.log("MarketInfo shortToken is non-zero address"); 108 | | } 109 | | } 110 | | 111 | * | function _logMarketInfoBorrowingFactorPerSecondForLongsCoverage( 112 | | uint256 borrowingFactorPerSecondForLongs 113 | | ) internal { 114 | * | if (borrowingFactorPerSecondForLongs == 0) { 115 | * | fl.log("MarketInfo borrowingFactorPerSecondForLongs is 0"); 116 | | } 117 | * | if ( 118 | * | borrowingFactorPerSecondForLongs > 0 && 119 | | borrowingFactorPerSecondForLongs <= 1e6 120 | | ) { 121 | | fl.log( 122 | | "MarketInfo borrowingFactorPerSecondForLongs is between 0 and 1e6" 123 | | ); 124 | | } 125 | * | if ( 126 | * | borrowingFactorPerSecondForLongs > 1e6 && 127 | | borrowingFactorPerSecondForLongs <= 1e12 128 | | ) { 129 | | fl.log( 130 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e6 and 1e12" 131 | | ); 132 | | } 133 | * | if ( 134 | * | borrowingFactorPerSecondForLongs > 1e12 && 135 | | borrowingFactorPerSecondForLongs <= 1e18 136 | | ) { 137 | | fl.log( 138 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e12 and 1e18" 139 | | ); 140 | | } 141 | * | if ( 142 | * | borrowingFactorPerSecondForLongs > 1e18 && 143 | | borrowingFactorPerSecondForLongs <= 1e24 144 | | ) { 145 | | fl.log( 146 | | "MarketInfo borrowingFactorPerSecondForLongs is between 1e18 and 1e24" 147 | | ); 148 | | } 149 | * | if (borrowingFactorPerSecondForLongs > 1e24) { 150 | | fl.log( 151 | | "MarketInfo borrowingFactorPerSecondForLongs is greater than 1e24" 152 | | ); 153 | | } 154 | | } 155 | | 156 | * | function _logMarketInfoBorrowingFactorPerSecondForShortsCoverage( 157 | | uint256 borrowingFactorPerSecondForShorts 158 | | ) internal { 159 | * | if (borrowingFactorPerSecondForShorts == 0) { 160 | * | fl.log("MarketInfo borrowingFactorPerSecondForShorts is 0"); 161 | | } 162 | * | if ( 163 | * | borrowingFactorPerSecondForShorts > 0 && 164 | | borrowingFactorPerSecondForShorts <= 1e6 165 | | ) { 166 | | fl.log( 167 | | "MarketInfo borrowingFactorPerSecondForShorts is between 0 and 1e6" 168 | | ); 169 | | } 170 | * | if ( 171 | * | borrowingFactorPerSecondForShorts > 1e6 && 172 | | borrowingFactorPerSecondForShorts <= 1e12 173 | | ) { 174 | | fl.log( 175 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e6 and 1e12" 176 | | ); 177 | | } 178 | * | if ( 179 | * | borrowingFactorPerSecondForShorts > 1e12 && 180 | | borrowingFactorPerSecondForShorts <= 1e18 181 | | ) { 182 | | fl.log( 183 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e12 and 1e18" 184 | | ); 185 | | } 186 | * | if ( 187 | * | borrowingFactorPerSecondForShorts > 1e18 && 188 | | borrowingFactorPerSecondForShorts <= 1e24 189 | | ) { 190 | | fl.log( 191 | | "MarketInfo borrowingFactorPerSecondForShorts is between 1e18 and 1e24" 192 | | ); 193 | | } 194 | * | if (borrowingFactorPerSecondForShorts > 1e24) { 195 | | fl.log( 196 | | "MarketInfo borrowingFactorPerSecondForShorts is greater than 1e24" 197 | | ); 198 | | } 199 | | } 200 | | 201 | * | function _logMarketInfoBaseFundingLongFundingFeeAmountPerSizeCoverage( 202 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSize 203 | | ) internal { 204 | * | if ( 205 | * | longFundingFeeAmountPerSize.longToken == 0 && 206 | * | longFundingFeeAmountPerSize.shortToken == 0 207 | | ) { 208 | * | fl.log( 209 | | "MarketInfo baseFunding longFundingFeeAmountPerSize is 0 for both longToken and shortToken" 210 | | ); 211 | | } 212 | * | if ( 213 | * | longFundingFeeAmountPerSize.longToken > 0 && 214 | * | longFundingFeeAmountPerSize.longToken <= 1e6 215 | | ) { 216 | | fl.log( 217 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 0 and 1e6" 218 | | ); 219 | | } 220 | * | if ( 221 | * | longFundingFeeAmountPerSize.longToken > 1e6 && 222 | * | longFundingFeeAmountPerSize.longToken <= 1e12 223 | | ) { 224 | | fl.log( 225 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e6 and 1e12" 226 | | ); 227 | | } 228 | * | if ( 229 | * | longFundingFeeAmountPerSize.longToken > 1e12 && 230 | * | longFundingFeeAmountPerSize.longToken <= 1e18 231 | | ) { 232 | * | fl.log( 233 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e12 and 1e18" 234 | | ); 235 | | } 236 | * | if ( 237 | * | longFundingFeeAmountPerSize.longToken > 1e18 && 238 | * | longFundingFeeAmountPerSize.longToken <= 1e24 239 | | ) { 240 | * | fl.log( 241 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is between 1e18 and 1e24" 242 | | ); 243 | | } 244 | * | if (longFundingFeeAmountPerSize.longToken > 1e24) { 245 | * | fl.log( 246 | | "MarketInfo baseFunding longFundingFeeAmountPerSize longToken is greater than 1e24" 247 | | ); 248 | | } 249 | * | if ( 250 | * | longFundingFeeAmountPerSize.shortToken > 0 && 251 | * | longFundingFeeAmountPerSize.shortToken <= 1e6 252 | | ) { 253 | | fl.log( 254 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 0 and 1e6" 255 | | ); 256 | | } 257 | * | if ( 258 | * | longFundingFeeAmountPerSize.shortToken > 1e6 && 259 | * | longFundingFeeAmountPerSize.shortToken <= 1e12 260 | | ) { 261 | | fl.log( 262 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e6 and 1e12" 263 | | ); 264 | | } 265 | * | if ( 266 | * | longFundingFeeAmountPerSize.shortToken > 1e12 && 267 | * | longFundingFeeAmountPerSize.shortToken <= 1e18 268 | | ) { 269 | | fl.log( 270 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e12 and 1e18" 271 | | ); 272 | | } 273 | * | if ( 274 | * | longFundingFeeAmountPerSize.shortToken > 1e18 && 275 | * | longFundingFeeAmountPerSize.shortToken <= 1e24 276 | | ) { 277 | * | fl.log( 278 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is between 1e18 and 1e24" 279 | | ); 280 | | } 281 | * | if (longFundingFeeAmountPerSize.shortToken > 1e24) { 282 | | fl.log( 283 | | "MarketInfo baseFunding longFundingFeeAmountPerSize shortToken is greater than 1e24" 284 | | ); 285 | | } 286 | | } 287 | | 288 | * | function _logMarketInfoBaseFundingShortFundingFeeAmountPerSizeCoverage( 289 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSize 290 | | ) internal { 291 | * | if ( 292 | * | shortFundingFeeAmountPerSize.longToken == 0 && 293 | * | shortFundingFeeAmountPerSize.shortToken == 0 294 | | ) { 295 | * | fl.log( 296 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize is 0 for both longToken and shortToken" 297 | | ); 298 | | } 299 | * | if ( 300 | * | shortFundingFeeAmountPerSize.longToken > 0 && 301 | | shortFundingFeeAmountPerSize.longToken <= 1e6 302 | | ) { 303 | | fl.log( 304 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 0 and 1e6" 305 | | ); 306 | | } 307 | * | if ( 308 | * | shortFundingFeeAmountPerSize.longToken > 1e6 && 309 | | shortFundingFeeAmountPerSize.longToken <= 1e12 310 | | ) { 311 | | fl.log( 312 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e6 and 1e12" 313 | | ); 314 | | } 315 | * | if ( 316 | * | shortFundingFeeAmountPerSize.longToken > 1e12 && 317 | | shortFundingFeeAmountPerSize.longToken <= 1e18 318 | | ) { 319 | | fl.log( 320 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e12 and 1e18" 321 | | ); 322 | | } 323 | * | if ( 324 | * | shortFundingFeeAmountPerSize.longToken > 1e18 && 325 | | shortFundingFeeAmountPerSize.longToken <= 1e24 326 | | ) { 327 | | fl.log( 328 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is between 1e18 and 1e24" 329 | | ); 330 | | } 331 | * | if (shortFundingFeeAmountPerSize.longToken > 1e24) { 332 | | fl.log( 333 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize longToken is greater than 1e24" 334 | | ); 335 | | } 336 | * | if ( 337 | * | shortFundingFeeAmountPerSize.shortToken > 0 && 338 | * | shortFundingFeeAmountPerSize.shortToken <= 1e6 339 | | ) { 340 | | fl.log( 341 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 0 and 1e6" 342 | | ); 343 | | } 344 | * | if ( 345 | * | shortFundingFeeAmountPerSize.shortToken > 1e6 && 346 | * | shortFundingFeeAmountPerSize.shortToken <= 1e12 347 | | ) { 348 | | fl.log( 349 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e6 and 1e12" 350 | | ); 351 | | } 352 | * | if ( 353 | * | shortFundingFeeAmountPerSize.shortToken > 1e12 && 354 | * | shortFundingFeeAmountPerSize.shortToken <= 1e18 355 | | ) { 356 | * | fl.log( 357 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e12 and 1e18" 358 | | ); 359 | | } 360 | * | if ( 361 | * | shortFundingFeeAmountPerSize.shortToken > 1e18 && 362 | * | shortFundingFeeAmountPerSize.shortToken <= 1e24 363 | | ) { 364 | * | fl.log( 365 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is between 1e18 and 1e24" 366 | | ); 367 | | } 368 | * | if (shortFundingFeeAmountPerSize.shortToken > 1e24) { 369 | | fl.log( 370 | | "MarketInfo baseFunding shortFundingFeeAmountPerSize shortToken is greater than 1e24" 371 | | ); 372 | | } 373 | | } 374 | | 375 | * | function _logMarketInfoBaseFundingLongClaimableFundingAmountPerSizeCoverage( 376 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSize 377 | | ) internal { 378 | * | if ( 379 | * | longClaimableFundingAmountPerSize.longToken == 0 && 380 | * | longClaimableFundingAmountPerSize.shortToken == 0 381 | | ) { 382 | * | fl.log( 383 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize is 0 for both longToken and shortToken" 384 | | ); 385 | | } 386 | * | if ( 387 | * | longClaimableFundingAmountPerSize.longToken > 0 && 388 | | longClaimableFundingAmountPerSize.longToken <= 1e6 389 | | ) { 390 | | fl.log( 391 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 0 and 1e6" 392 | | ); 393 | | } 394 | * | if ( 395 | * | longClaimableFundingAmountPerSize.longToken > 1e6 && 396 | | longClaimableFundingAmountPerSize.longToken <= 1e12 397 | | ) { 398 | | fl.log( 399 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e6 and 1e12" 400 | | ); 401 | | } 402 | * | if ( 403 | * | longClaimableFundingAmountPerSize.longToken > 1e12 && 404 | | longClaimableFundingAmountPerSize.longToken <= 1e18 405 | | ) { 406 | | fl.log( 407 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e12 and 1e18" 408 | | ); 409 | | } 410 | * | if ( 411 | * | longClaimableFundingAmountPerSize.longToken > 1e18 && 412 | | longClaimableFundingAmountPerSize.longToken <= 1e24 413 | | ) { 414 | | fl.log( 415 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is between 1e18 and 1e24" 416 | | ); 417 | | } 418 | * | if (longClaimableFundingAmountPerSize.longToken > 1e24) { 419 | | fl.log( 420 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize longToken is greater than 1e24" 421 | | ); 422 | | } 423 | * | if ( 424 | * | longClaimableFundingAmountPerSize.shortToken > 0 && 425 | * | longClaimableFundingAmountPerSize.shortToken <= 1e6 426 | | ) { 427 | | fl.log( 428 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 0 and 1e6" 429 | | ); 430 | | } 431 | * | if ( 432 | * | longClaimableFundingAmountPerSize.shortToken > 1e6 && 433 | * | longClaimableFundingAmountPerSize.shortToken <= 1e12 434 | | ) { 435 | | fl.log( 436 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12" 437 | | ); 438 | | } 439 | * | if ( 440 | * | longClaimableFundingAmountPerSize.shortToken > 1e12 && 441 | * | longClaimableFundingAmountPerSize.shortToken <= 1e18 442 | | ) { 443 | | fl.log( 444 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18" 445 | | ); 446 | | } 447 | * | if ( 448 | * | longClaimableFundingAmountPerSize.shortToken > 1e18 && 449 | * | longClaimableFundingAmountPerSize.shortToken <= 1e24 450 | | ) { 451 | * | fl.log( 452 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24" 453 | | ); 454 | | } 455 | * | if (longClaimableFundingAmountPerSize.shortToken > 1e24) { 456 | * | fl.log( 457 | | "MarketInfo baseFunding longClaimableFundingAmountPerSize shortToken is greater than 1e24" 458 | | ); 459 | | } 460 | | } 461 | | 462 | * | function _logMarketInfoBaseFundingShortClaimableFundingAmountPerSizeCoverage( 463 | | MarketUtils.CollateralType memory shortClaimableFundingAmountPerSize 464 | | ) internal { 465 | * | if ( 466 | * | shortClaimableFundingAmountPerSize.longToken == 0 && 467 | * | shortClaimableFundingAmountPerSize.shortToken == 0 468 | | ) { 469 | * | fl.log( 470 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize is 0 for both longToken and shortToken" 471 | | ); 472 | | } 473 | * | if ( 474 | * | shortClaimableFundingAmountPerSize.longToken > 0 && 475 | * | shortClaimableFundingAmountPerSize.longToken <= 1e6 476 | | ) { 477 | | fl.log( 478 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 0 and 1e6" 479 | | ); 480 | | } 481 | * | if ( 482 | * | shortClaimableFundingAmountPerSize.longToken > 1e6 && 483 | * | shortClaimableFundingAmountPerSize.longToken <= 1e12 484 | | ) { 485 | | fl.log( 486 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e6 and 1e12" 487 | | ); 488 | | } 489 | * | if ( 490 | * | shortClaimableFundingAmountPerSize.longToken > 1e12 && 491 | * | shortClaimableFundingAmountPerSize.longToken <= 1e18 492 | | ) { 493 | * | fl.log( 494 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e12 and 1e18" 495 | | ); 496 | | } 497 | * | if ( 498 | * | shortClaimableFundingAmountPerSize.longToken > 1e18 && 499 | * | shortClaimableFundingAmountPerSize.longToken <= 1e24 500 | | ) { 501 | * | fl.log( 502 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is between 1e18 and 1e24" 503 | | ); 504 | | } 505 | * | if (shortClaimableFundingAmountPerSize.longToken > 1e24) { 506 | * | fl.log( 507 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize longToken is greater than 1e24" 508 | | ); 509 | | } 510 | * | if ( 511 | * | shortClaimableFundingAmountPerSize.shortToken > 0 && 512 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e6 513 | | ) { 514 | | fl.log( 515 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 0 and 1e6" 516 | | ); 517 | | } 518 | * | if ( 519 | * | shortClaimableFundingAmountPerSize.shortToken > 1e6 && 520 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e12 521 | | ) { 522 | | fl.log( 523 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e6 and 1e12" 524 | | ); 525 | | } 526 | * | if ( 527 | * | shortClaimableFundingAmountPerSize.shortToken > 1e12 && 528 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e18 529 | | ) { 530 | * | fl.log( 531 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e12 and 1e18" 532 | | ); 533 | | } 534 | * | if ( 535 | * | shortClaimableFundingAmountPerSize.shortToken > 1e18 && 536 | * | shortClaimableFundingAmountPerSize.shortToken <= 1e24 537 | | ) { 538 | * | fl.log( 539 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is between 1e18 and 1e24" 540 | | ); 541 | | } 542 | * | if (shortClaimableFundingAmountPerSize.shortToken > 1e24) { 543 | * | fl.log( 544 | | "MarketInfo baseFunding shortClaimableFundingAmountPerSize shortToken is greater than 1e24" 545 | | ); 546 | | } 547 | | } 548 | | 549 | * | function _logMarketInfoNextFundingLongsPayShortsCoverage( 550 | | bool longsPayShorts 551 | | ) internal { 552 | * | if (longsPayShorts) { 553 | * | fl.log("MarketInfo nextFunding longsPayShorts is true"); 554 | | } else { 555 | * | fl.log("MarketInfo nextFunding longsPayShorts is false"); 556 | | } 557 | | } 558 | | 559 | * | function _logMarketInfoNextFundingFundingFactorPerSecondCoverage( 560 | | uint256 fundingFactorPerSecond 561 | | ) internal { 562 | * | if (fundingFactorPerSecond == 0) { 563 | * | fl.log("MarketInfo nextFunding fundingFactorPerSecond is 0"); 564 | | } 565 | * | if (fundingFactorPerSecond > 0 && fundingFactorPerSecond <= 1e6) { 566 | | fl.log( 567 | | "MarketInfo nextFunding fundingFactorPerSecond is between 0 and 1e6" 568 | | ); 569 | | } 570 | * | if (fundingFactorPerSecond > 1e6 && fundingFactorPerSecond <= 1e12) { 571 | | fl.log( 572 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e6 and 1e12" 573 | | ); 574 | | } 575 | * | if (fundingFactorPerSecond > 1e12 && fundingFactorPerSecond <= 1e18) { 576 | | fl.log( 577 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e12 and 1e18" 578 | | ); 579 | | } 580 | * | if (fundingFactorPerSecond > 1e18 && fundingFactorPerSecond <= 1e24) { 581 | * | fl.log( 582 | | "MarketInfo nextFunding fundingFactorPerSecond is between 1e18 and 1e24" 583 | | ); 584 | | } 585 | * | if (fundingFactorPerSecond > 1e24) { 586 | * | fl.log( 587 | | "MarketInfo nextFunding fundingFactorPerSecond is greater than 1e24" 588 | | ); 589 | | } 590 | | } 591 | | 592 | * | function _logMarketInfoNextFundingNextSavedFundingFactorPerSecondCoverage( 593 | | int256 nextSavedFundingFactorPerSecond 594 | | ) internal { 595 | * | if (nextSavedFundingFactorPerSecond == 0) { 596 | * | fl.log( 597 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is 0" 598 | | ); 599 | | } 600 | * | if ( 601 | * | nextSavedFundingFactorPerSecond > 0 && 602 | | nextSavedFundingFactorPerSecond <= 1e6 603 | | ) { 604 | | fl.log( 605 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and 1e6" 606 | | ); 607 | | } 608 | * | if ( 609 | * | nextSavedFundingFactorPerSecond > 1e6 && 610 | | nextSavedFundingFactorPerSecond <= 1e12 611 | | ) { 612 | | fl.log( 613 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e6 and 1e12" 614 | | ); 615 | | } 616 | * | if ( 617 | * | nextSavedFundingFactorPerSecond > 1e12 && 618 | | nextSavedFundingFactorPerSecond <= 1e18 619 | | ) { 620 | | fl.log( 621 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e12 and 1e18" 622 | | ); 623 | | } 624 | * | if ( 625 | * | nextSavedFundingFactorPerSecond > 1e18 && 626 | | nextSavedFundingFactorPerSecond <= 1e24 627 | | ) { 628 | | fl.log( 629 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 1e18 and 1e24" 630 | | ); 631 | | } 632 | * | if (nextSavedFundingFactorPerSecond > 1e24) { 633 | | fl.log( 634 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is greater than 1e24" 635 | | ); 636 | | } 637 | * | if ( 638 | * | nextSavedFundingFactorPerSecond < 0 && 639 | | nextSavedFundingFactorPerSecond >= -1e6 640 | | ) { 641 | | fl.log( 642 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between 0 and -1e6" 643 | | ); 644 | | } 645 | * | if ( 646 | * | nextSavedFundingFactorPerSecond < -1e6 && 647 | | nextSavedFundingFactorPerSecond >= -1e12 648 | | ) { 649 | | fl.log( 650 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e6 and -1e12" 651 | | ); 652 | | } 653 | * | if ( 654 | * | nextSavedFundingFactorPerSecond < -1e12 && 655 | | nextSavedFundingFactorPerSecond >= -1e18 656 | | ) { 657 | | fl.log( 658 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e12 and -1e18" 659 | | ); 660 | | } 661 | * | if ( 662 | * | nextSavedFundingFactorPerSecond < -1e18 && 663 | | nextSavedFundingFactorPerSecond >= -1e24 664 | | ) { 665 | | fl.log( 666 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is between -1e18 and -1e24" 667 | | ); 668 | | } 669 | * | if (nextSavedFundingFactorPerSecond < -1e24) { 670 | | fl.log( 671 | | "MarketInfo nextFunding nextSavedFundingFactorPerSecond is less than -1e24" 672 | | ); 673 | | } 674 | | } 675 | | 676 | * | function _logMarketInfoNextFundingLongFundingFeeAmountPerSizeDeltaCoverage( 677 | | MarketUtils.CollateralType memory longFundingFeeAmountPerSizeDelta 678 | | ) internal { 679 | * | if ( 680 | * | longFundingFeeAmountPerSizeDelta.longToken == 0 && 681 | * | longFundingFeeAmountPerSizeDelta.shortToken == 0 682 | | ) { 683 | * | fl.log( 684 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken" 685 | | ); 686 | | } 687 | * | if ( 688 | * | longFundingFeeAmountPerSizeDelta.longToken > 0 && 689 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e6 690 | | ) { 691 | | fl.log( 692 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6" 693 | | ); 694 | | } 695 | * | if ( 696 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e6 && 697 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e12 698 | | ) { 699 | | fl.log( 700 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12" 701 | | ); 702 | | } 703 | * | if ( 704 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e12 && 705 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e18 706 | | ) { 707 | * | fl.log( 708 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18" 709 | | ); 710 | | } 711 | * | if ( 712 | * | longFundingFeeAmountPerSizeDelta.longToken > 1e18 && 713 | * | longFundingFeeAmountPerSizeDelta.longToken <= 1e24 714 | | ) { 715 | | fl.log( 716 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24" 717 | | ); 718 | | } 719 | * | if (longFundingFeeAmountPerSizeDelta.longToken > 1e24) { 720 | * | fl.log( 721 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta longToken is greater than 1e24" 722 | | ); 723 | | } 724 | * | if ( 725 | * | longFundingFeeAmountPerSizeDelta.shortToken > 0 && 726 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e6 727 | | ) { 728 | | fl.log( 729 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6" 730 | | ); 731 | | } 732 | * | if ( 733 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e6 && 734 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e12 735 | | ) { 736 | | fl.log( 737 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12" 738 | | ); 739 | | } 740 | * | if ( 741 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e12 && 742 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e18 743 | | ) { 744 | * | fl.log( 745 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18" 746 | | ); 747 | | } 748 | * | if ( 749 | * | longFundingFeeAmountPerSizeDelta.shortToken > 1e18 && 750 | * | longFundingFeeAmountPerSizeDelta.shortToken <= 1e24 751 | | ) { 752 | * | fl.log( 753 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24" 754 | | ); 755 | | } 756 | * | if (longFundingFeeAmountPerSizeDelta.shortToken > 1e24) { 757 | | fl.log( 758 | | "MarketInfo nextFund longFundingFeeAmountPerSizeDelta shortToken is greater than 1e24" 759 | | ); 760 | | } 761 | | } 762 | * | function _logMarketInfoNextFundingShortFundingFeeAmountPerSizeDeltaCoverage( 763 | | MarketUtils.CollateralType memory shortFundingFeeAmountPerSizeDelta 764 | | ) internal { 765 | * | if ( 766 | * | shortFundingFeeAmountPerSizeDelta.longToken == 0 && 767 | * | shortFundingFeeAmountPerSizeDelta.shortToken == 0 768 | | ) { 769 | * | fl.log( 770 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta is 0 for both longToken and shortToken" 771 | | ); 772 | | } 773 | * | if ( 774 | * | shortFundingFeeAmountPerSizeDelta.longToken > 0 && 775 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e6 776 | | ) { 777 | | fl.log( 778 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 0 and 1e6" 779 | | ); 780 | | } 781 | * | if ( 782 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e6 && 783 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e12 784 | | ) { 785 | | fl.log( 786 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e6 and 1e12" 787 | | ); 788 | | } 789 | * | if ( 790 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e12 && 791 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e18 792 | | ) { 793 | | fl.log( 794 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e12 and 1e18" 795 | | ); 796 | | } 797 | * | if ( 798 | * | shortFundingFeeAmountPerSizeDelta.longToken > 1e18 && 799 | | shortFundingFeeAmountPerSizeDelta.longToken <= 1e24 800 | | ) { 801 | | fl.log( 802 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is between 1e18 and 1e24" 803 | | ); 804 | | } 805 | * | if (shortFundingFeeAmountPerSizeDelta.longToken > 1e24) { 806 | | fl.log( 807 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta longToken is greater than 1e24" 808 | | ); 809 | | } 810 | * | if ( 811 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 0 && 812 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e6 813 | | ) { 814 | | fl.log( 815 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 0 and 1e6" 816 | | ); 817 | | } 818 | * | if ( 819 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e6 && 820 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e12 821 | | ) { 822 | | fl.log( 823 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e6 and 1e12" 824 | | ); 825 | | } 826 | * | if ( 827 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e12 && 828 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e18 829 | | ) { 830 | * | fl.log( 831 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e12 and 1e18" 832 | | ); 833 | | } 834 | * | if ( 835 | * | shortFundingFeeAmountPerSizeDelta.shortToken > 1e18 && 836 | * | shortFundingFeeAmountPerSizeDelta.shortToken <= 1e24 837 | | ) { 838 | * | fl.log( 839 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is between 1e18 and 1e24" 840 | | ); 841 | | } 842 | * | if (shortFundingFeeAmountPerSizeDelta.shortToken > 1e24) { 843 | | fl.log( 844 | | "MarketInfo nextFunding shortFundingFeeAmountPerSizeDelta shortToken is greater than 1e24" 845 | | ); 846 | | } 847 | | } 848 | | 849 | * | function _logMarketInfoNextFundingLongClaimableFundingAmountPerSizeDeltaCoverage( 850 | | MarketUtils.CollateralType memory longClaimableFundingAmountPerSizeDelta 851 | | ) internal { 852 | * | if ( 853 | * | longClaimableFundingAmountPerSizeDelta.longToken == 0 && 854 | * | longClaimableFundingAmountPerSizeDelta.shortToken == 0 855 | | ) { 856 | * | fl.log( 857 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken" 858 | | ); 859 | | } 860 | * | if ( 861 | * | longClaimableFundingAmountPerSizeDelta.longToken > 0 && 862 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e6 863 | | ) { 864 | | fl.log( 865 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6" 866 | | ); 867 | | } 868 | * | if ( 869 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e6 && 870 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e12 871 | | ) { 872 | | fl.log( 873 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12" 874 | | ); 875 | | } 876 | * | if ( 877 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e12 && 878 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e18 879 | | ) { 880 | | fl.log( 881 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18" 882 | | ); 883 | | } 884 | * | if ( 885 | * | longClaimableFundingAmountPerSizeDelta.longToken > 1e18 && 886 | | longClaimableFundingAmountPerSizeDelta.longToken <= 1e24 887 | | ) { 888 | | fl.log( 889 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24" 890 | | ); 891 | | } 892 | * | if (longClaimableFundingAmountPerSizeDelta.longToken > 1e24) { 893 | | fl.log( 894 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta longToken is greater than 1e24" 895 | | ); 896 | | } 897 | * | if ( 898 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 0 && 899 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e6 900 | | ) { 901 | | fl.log( 902 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6" 903 | | ); 904 | | } 905 | * | if ( 906 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e6 && 907 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e12 908 | | ) { 909 | | fl.log( 910 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12" 911 | | ); 912 | | } 913 | * | if ( 914 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e12 && 915 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e18 916 | | ) { 917 | * | fl.log( 918 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18" 919 | | ); 920 | | } 921 | * | if ( 922 | * | longClaimableFundingAmountPerSizeDelta.shortToken > 1e18 && 923 | * | longClaimableFundingAmountPerSizeDelta.shortToken <= 1e24 924 | | ) { 925 | * | fl.log( 926 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24" 927 | | ); 928 | | } 929 | * | if (longClaimableFundingAmountPerSizeDelta.shortToken > 1e24) { 930 | | fl.log( 931 | | "MarketInfo nextFunding longClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24" 932 | | ); 933 | | } 934 | | } 935 | | 936 | * | function _logMarketInfoNextFundingShortClaimableFundingAmountPerSizeDeltaCoverage( 937 | | MarketUtils.CollateralType 938 | | memory shortClaimableFundingAmountPerSizeDelta 939 | | ) internal { 940 | * | if ( 941 | * | shortClaimableFundingAmountPerSizeDelta.longToken == 0 && 942 | * | shortClaimableFundingAmountPerSizeDelta.shortToken == 0 943 | | ) { 944 | * | fl.log( 945 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta is 0 for both longToken and shortToken" 946 | | ); 947 | | } 948 | * | if ( 949 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 0 && 950 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e6 951 | | ) { 952 | | fl.log( 953 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 0 and 1e6" 954 | | ); 955 | | } 956 | * | if ( 957 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e6 && 958 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e12 959 | | ) { 960 | | fl.log( 961 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e6 and 1e12" 962 | | ); 963 | | } 964 | * | if ( 965 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e12 && 966 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e18 967 | | ) { 968 | * | fl.log( 969 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e12 and 1e18" 970 | | ); 971 | | } 972 | * | if ( 973 | * | shortClaimableFundingAmountPerSizeDelta.longToken > 1e18 && 974 | * | shortClaimableFundingAmountPerSizeDelta.longToken <= 1e24 975 | | ) { 976 | * | fl.log( 977 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is between 1e18 and 1e24" 978 | | ); 979 | | } 980 | * | if (shortClaimableFundingAmountPerSizeDelta.longToken > 1e24) { 981 | * | fl.log( 982 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta longToken is greater than 1e24" 983 | | ); 984 | | } 985 | * | if ( 986 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 0 && 987 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e6 988 | | ) { 989 | | fl.log( 990 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 0 and 1e6" 991 | | ); 992 | | } 993 | * | if ( 994 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e6 && 995 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e12 996 | | ) { 997 | | fl.log( 998 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e6 and 1e12" 999 | | ); 1000 | | } 1001 | * | if ( 1002 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e12 && 1003 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e18 1004 | | ) { 1005 | * | fl.log( 1006 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e12 and 1e18" 1007 | | ); 1008 | | } 1009 | * | if ( 1010 | * | shortClaimableFundingAmountPerSizeDelta.shortToken > 1e18 && 1011 | * | shortClaimableFundingAmountPerSizeDelta.shortToken <= 1e24 1012 | | ) { 1013 | * | fl.log( 1014 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is between 1e18 and 1e24" 1015 | | ); 1016 | | } 1017 | * | if (shortClaimableFundingAmountPerSizeDelta.shortToken > 1e24) { 1018 | * | fl.log( 1019 | | "MarketInfo nextFunding shortClaimableFundingAmountPerSizeDelta shortToken is greater than 1e24" 1020 | | ); 1021 | | } 1022 | | } 1023 | | 1024 | * | function _logMarketInfoVirtualInventoryVirtualPoolAmountForLongTokenCoverage( 1025 | | uint256 virtualPoolAmountForLongToken 1026 | | ) internal { 1027 | * | if (virtualPoolAmountForLongToken == 0) { 1028 | * | fl.log( 1029 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is 0" 1030 | | ); 1031 | | } 1032 | * | if ( 1033 | * | virtualPoolAmountForLongToken > 0 && 1034 | | virtualPoolAmountForLongToken <= 1e6 1035 | | ) { 1036 | | fl.log( 1037 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 0 and 1e6" 1038 | | ); 1039 | | } 1040 | * | if ( 1041 | * | virtualPoolAmountForLongToken > 1e6 && 1042 | | virtualPoolAmountForLongToken <= 1e12 1043 | | ) { 1044 | | fl.log( 1045 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e6 and 1e12" 1046 | | ); 1047 | | } 1048 | * | if ( 1049 | * | virtualPoolAmountForLongToken > 1e12 && 1050 | | virtualPoolAmountForLongToken <= 1e18 1051 | | ) { 1052 | | fl.log( 1053 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e12 and 1e18" 1054 | | ); 1055 | | } 1056 | * | if ( 1057 | * | virtualPoolAmountForLongToken > 1e18 && 1058 | | virtualPoolAmountForLongToken <= 1e24 1059 | | ) { 1060 | | fl.log( 1061 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is between 1e18 and 1e24" 1062 | | ); 1063 | | } 1064 | * | if (virtualPoolAmountForLongToken > 1e24) { 1065 | | fl.log( 1066 | | "MarketInfo virtualInventory virtualPoolAmountForLongToken is greater than 1e24" 1067 | | ); 1068 | | } 1069 | | } 1070 | | 1071 | * | function _logMarketInfoVirtualInventoryVirtualPoolAmountForShortTokenCoverage( 1072 | | uint256 virtualPoolAmountForShortToken 1073 | | ) internal { 1074 | * | if (virtualPoolAmountForShortToken == 0) { 1075 | * | fl.log( 1076 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is 0" 1077 | | ); 1078 | | } 1079 | * | if ( 1080 | * | virtualPoolAmountForShortToken > 0 && 1081 | | virtualPoolAmountForShortToken <= 1e6 1082 | | ) { 1083 | | fl.log( 1084 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 0 and 1e6" 1085 | | ); 1086 | | } 1087 | * | if ( 1088 | * | virtualPoolAmountForShortToken > 1e6 && 1089 | | virtualPoolAmountForShortToken <= 1e12 1090 | | ) { 1091 | | fl.log( 1092 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e6 and 1e12" 1093 | | ); 1094 | | } 1095 | * | if ( 1096 | * | virtualPoolAmountForShortToken > 1e12 && 1097 | | virtualPoolAmountForShortToken <= 1e18 1098 | | ) { 1099 | | fl.log( 1100 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e12 and 1e18" 1101 | | ); 1102 | | } 1103 | * | if ( 1104 | * | virtualPoolAmountForShortToken > 1e18 && 1105 | | virtualPoolAmountForShortToken <= 1e24 1106 | | ) { 1107 | | fl.log( 1108 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is between 1e18 and 1e24" 1109 | | ); 1110 | | } 1111 | * | if (virtualPoolAmountForShortToken > 1e24) { 1112 | | fl.log( 1113 | | "MarketInfo virtualInventory virtualPoolAmountForShortToken is greater than 1e24" 1114 | | ); 1115 | | } 1116 | | } 1117 | | 1118 | * | function _logMarketInfoVirtualInventoryVirtualInventoryForPositionsCoverage( 1119 | | int256 virtualInventoryForPositions 1120 | | ) internal { 1121 | * | if (virtualInventoryForPositions == 0) { 1122 | * | fl.log( 1123 | | "MarketInfo virtualInventory virtualInventoryForPositions is 0" 1124 | | ); 1125 | | } 1126 | * | if ( 1127 | * | virtualInventoryForPositions > 0 && 1128 | | virtualInventoryForPositions <= 1e6 1129 | | ) { 1130 | | fl.log( 1131 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and 1e6" 1132 | | ); 1133 | | } 1134 | * | if ( 1135 | * | virtualInventoryForPositions > 1e6 && 1136 | | virtualInventoryForPositions <= 1e12 1137 | | ) { 1138 | | fl.log( 1139 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e6 and 1e12" 1140 | | ); 1141 | | } 1142 | * | if ( 1143 | * | virtualInventoryForPositions > 1e12 && 1144 | | virtualInventoryForPositions <= 1e18 1145 | | ) { 1146 | | fl.log( 1147 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e12 and 1e18" 1148 | | ); 1149 | | } 1150 | * | if ( 1151 | * | virtualInventoryForPositions > 1e18 && 1152 | | virtualInventoryForPositions <= 1e24 1153 | | ) { 1154 | | fl.log( 1155 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 1e18 and 1e24" 1156 | | ); 1157 | | } 1158 | * | if (virtualInventoryForPositions > 1e24) { 1159 | | fl.log( 1160 | | "MarketInfo virtualInventory virtualInventoryForPositions is greater than 1e24" 1161 | | ); 1162 | | } 1163 | * | if ( 1164 | * | virtualInventoryForPositions < 0 && 1165 | | virtualInventoryForPositions >= -1e6 1166 | | ) { 1167 | | fl.log( 1168 | | "MarketInfo virtualInventory virtualInventoryForPositions is between 0 and -1e6" 1169 | | ); 1170 | | } 1171 | * | if ( 1172 | * | virtualInventoryForPositions < -1e6 && 1173 | | virtualInventoryForPositions >= -1e12 1174 | | ) { 1175 | | fl.log( 1176 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e6 and -1e12" 1177 | | ); 1178 | | } 1179 | * | if ( 1180 | * | virtualInventoryForPositions < -1e12 && 1181 | | virtualInventoryForPositions >= -1e18 1182 | | ) { 1183 | | fl.log( 1184 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e12 and -1e18" 1185 | | ); 1186 | | } 1187 | * | if ( 1188 | * | virtualInventoryForPositions < -1e18 && 1189 | | virtualInventoryForPositions >= -1e24 1190 | | ) { 1191 | | fl.log( 1192 | | "MarketInfo virtualInventory virtualInventoryForPositions is between -1e18 and -1e24" 1193 | | ); 1194 | | } 1195 | * | if (virtualInventoryForPositions < -1e24) { 1196 | | fl.log( 1197 | | "MarketInfo virtualInventory virtualInventoryForPositions is less than -1e24" 1198 | | ); 1199 | | } 1200 | | } 1201 | | 1202 | * | function _logMarketInfoIsDisabledCoverage(bool isDisabled) internal { 1203 | * | if (isDisabled) { 1204 | | fl.log("MarketInfo isDisabled is true"); 1205 | | } else { 1206 | * | fl.log("MarketInfo isDisabled is false"); 1207 | | } 1208 | | } 1209 | | } 1210 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftCancelCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract ShiftCancelCoverage is BeforeAfter {} 8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftCreatedCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract ShiftCreatedCoverage is BeforeAfter {} 8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/shiftCoverage/ShiftExecutedCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract ShiftExecutedCoverage is BeforeAfter {} 8 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalCancelCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract WithdrawalCancelCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ CANCEL WITHDRAWAL COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | * | function _checkCancelWithdrawalCoverage( 14 | | Withdrawal.Props memory withdrawalProps 15 | | ) internal { 16 | * | _logWithdrawalAccountCoverage_cancelWithdrawal( 17 | * | withdrawalProps.addresses.account 18 | | ); 19 | * | _logWithdrawalReceiverCoverage_cancelWithdrawal( 20 | * | withdrawalProps.addresses.receiver 21 | | ); 22 | * | _logWithdrawalCallbackContractCoverage_cancelWithdrawal( 23 | * | withdrawalProps.addresses.callbackContract 24 | | ); 25 | * | _logWithdrawalUiFeeReceiverCoverage_cancelWithdrawal( 26 | * | withdrawalProps.addresses.uiFeeReceiver 27 | | ); 28 | * | _logWithdrawalMarketCoverage_cancelWithdrawal( 29 | * | withdrawalProps.addresses.market 30 | | ); 31 | * | _logWithdrawalLongTokenSwapPathCoverage_cancelWithdrawal( 32 | * | withdrawalProps.addresses.longTokenSwapPath 33 | | ); 34 | * | _logWithdrawalShortTokenSwapPathCoverage_cancelWithdrawal( 35 | * | withdrawalProps.addresses.shortTokenSwapPath 36 | | ); 37 | * | _logWithdrawalMarketTokenAmountCoverage_cancelWithdrawal( 38 | * | withdrawalProps.numbers.marketTokenAmount 39 | | ); 40 | * | _logWithdrawalMinLongTokenAmountCoverage_cancelWithdrawal( 41 | * | withdrawalProps.numbers.minLongTokenAmount 42 | | ); 43 | * | _logWithdrawalMinShortTokenAmountCoverage_cancelWithdrawal( 44 | * | withdrawalProps.numbers.minShortTokenAmount 45 | | ); 46 | * | _logWithdrawalUpdatedAtBlockCoverage_cancelWithdrawal( 47 | * | withdrawalProps.numbers.updatedAtBlock 48 | | ); 49 | * | _logWithdrawalUpdatedAtTimeCoverage_cancelWithdrawal( 50 | * | withdrawalProps.numbers.updatedAtTime 51 | | ); 52 | * | _logWithdrawalExecutionFeeCoverage_cancelWithdrawal( 53 | * | withdrawalProps.numbers.executionFee 54 | | ); 55 | * | _logWithdrawalCallbackGasLimitCoverage_cancelWithdrawal( 56 | * | withdrawalProps.numbers.callbackGasLimit 57 | | ); 58 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage_cancelWithdrawal( 59 | * | withdrawalProps.flags.shouldUnwrapNativeToken 60 | | ); 61 | | } 62 | | 63 | * | function _logWithdrawalAccountCoverage_cancelWithdrawal( 64 | | address account 65 | | ) internal { 66 | * | if (account == USER0) { 67 | * | fl.log("Withdrawal account USER0 hit"); 68 | | } 69 | * | if (account == USER1) { 70 | | fl.log("Withdrawal account USER1 hit"); 71 | | } 72 | * | if (account == USER2) { 73 | | fl.log("Withdrawal account USER2 hit"); 74 | | } 75 | * | if (account == USER3) { 76 | | fl.log("Withdrawal account USER3 hit"); 77 | | } 78 | * | if (account == USER4) { 79 | | fl.log("Withdrawal account USER4 hit"); 80 | | } 81 | * | if (account == USER5) { 82 | | fl.log("Withdrawal account USER5 hit"); 83 | | } 84 | * | if (account == USER6) { 85 | | fl.log("Withdrawal account USER6 hit"); 86 | | } 87 | * | if (account == USER7) { 88 | | fl.log("Withdrawal account USER7 hit"); 89 | | } 90 | * | if (account == USER8) { 91 | | fl.log("Withdrawal account USER8 hit"); 92 | | } 93 | * | if (account == USER9) { 94 | | fl.log("Withdrawal account USER9 hit"); 95 | | } 96 | * | if (account == USER10) { 97 | | fl.log("Withdrawal account USER10 hit"); 98 | | } 99 | * | if (account == USER11) { 100 | | fl.log("Withdrawal account USER11 hit"); 101 | | } 102 | * | if (account == USER12) { 103 | | fl.log("Withdrawal account USER12 hit"); 104 | | } 105 | * | if (account == USER13) { 106 | | fl.log("Withdrawal account USER13 hit"); 107 | | } 108 | | } 109 | | 110 | * | function _logWithdrawalReceiverCoverage_cancelWithdrawal( 111 | | address receiver 112 | | ) internal { 113 | * | if (receiver == USER0) { 114 | * | fl.log("Withdrawal receiver USER0 hit"); 115 | | } 116 | * | if (receiver == USER1) { 117 | | fl.log("Withdrawal receiver USER1 hit"); 118 | | } 119 | * | if (receiver == USER2) { 120 | | fl.log("Withdrawal receiver USER2 hit"); 121 | | } 122 | * | if (receiver == USER3) { 123 | | fl.log("Withdrawal receiver USER3 hit"); 124 | | } 125 | * | if (receiver == USER4) { 126 | | fl.log("Withdrawal receiver USER4 hit"); 127 | | } 128 | * | if (receiver == USER5) { 129 | | fl.log("Withdrawal receiver USER5 hit"); 130 | | } 131 | * | if (receiver == USER6) { 132 | | fl.log("Withdrawal receiver USER6 hit"); 133 | | } 134 | * | if (receiver == USER7) { 135 | | fl.log("Withdrawal receiver USER7 hit"); 136 | | } 137 | * | if (receiver == USER8) { 138 | | fl.log("Withdrawal receiver USER8 hit"); 139 | | } 140 | * | if (receiver == USER9) { 141 | | fl.log("Withdrawal receiver USER9 hit"); 142 | | } 143 | * | if (receiver == USER10) { 144 | | fl.log("Withdrawal receiver USER10 hit"); 145 | | } 146 | * | if (receiver == USER11) { 147 | | fl.log("Withdrawal receiver USER11 hit"); 148 | | } 149 | * | if (receiver == USER12) { 150 | | fl.log("Withdrawal receiver USER12 hit"); 151 | | } 152 | * | if (receiver == USER13) { 153 | | fl.log("Withdrawal receiver USER13 hit"); 154 | | } 155 | | } 156 | * | function _logWithdrawalCallbackContractCoverage_cancelWithdrawal( 157 | | address callbackContract 158 | | ) internal { 159 | * | if (callbackContract == address(0)) { 160 | * | fl.log("Withdrawal callbackContract is address(0)"); 161 | | } else { 162 | | fl.log("Withdrawal callbackContract is non-zero address"); 163 | | } 164 | | } 165 | | 166 | * | function _logWithdrawalUiFeeReceiverCoverage_cancelWithdrawal( 167 | | address uiFeeReceiver 168 | | ) internal { 169 | * | if (uiFeeReceiver == address(0)) { 170 | * | fl.log("Withdrawal uiFeeReceiver is address(0)"); 171 | | } else { 172 | | fl.log("Withdrawal uiFeeReceiver is non-zero address"); 173 | | } 174 | | } 175 | | 176 | * | function _logWithdrawalMarketCoverage_cancelWithdrawal( 177 | | address market 178 | | ) internal { 179 | * | if (market == address(market_0_WETH_USDC)) { 180 | * | fl.log("Withdrawal market market_0_WETH_USDC hit"); 181 | | } 182 | | 183 | * | if (market == address(market_WBTC_WBTC_USDC)) { 184 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit"); 185 | | } 186 | * | if (market == address(market_WETH_WETH_USDC)) { 187 | * | fl.log("Withdrawal market market_WETH_WETH_USDC hit"); 188 | | } 189 | * | if (market == address(market_WETH_WETH_USDT)) { 190 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit"); 191 | | } 192 | | } 193 | | 194 | * | function _logWithdrawalLongTokenSwapPathCoverage_cancelWithdrawal( 195 | | address[] memory longTokenSwapPath 196 | | ) internal { 197 | * | if (longTokenSwapPath.length == 0) { 198 | * | fl.log("Withdrawal longTokenSwapPath is empty"); 199 | | } 200 | * | if (longTokenSwapPath.length == 1) { 201 | | fl.log("Withdrawal longTokenSwapPath has 1 element"); 202 | | } 203 | * | if (longTokenSwapPath.length == 2) { 204 | | fl.log("Withdrawal longTokenSwapPath has 2 elements"); 205 | | } 206 | * | if (longTokenSwapPath.length >= 3) { 207 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements"); 208 | | } 209 | | } 210 | | 211 | * | function _logWithdrawalShortTokenSwapPathCoverage_cancelWithdrawal( 212 | | address[] memory shortTokenSwapPath 213 | | ) internal { 214 | * | if (shortTokenSwapPath.length == 0) { 215 | * | fl.log("Withdrawal shortTokenSwapPath is empty"); 216 | | } 217 | * | if (shortTokenSwapPath.length == 1) { 218 | | fl.log("Withdrawal shortTokenSwapPath has 1 element"); 219 | | } 220 | * | if (shortTokenSwapPath.length == 2) { 221 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements"); 222 | | } 223 | * | if (shortTokenSwapPath.length >= 3) { 224 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements"); 225 | | } 226 | | } 227 | | 228 | * | function _logWithdrawalMarketTokenAmountCoverage_cancelWithdrawal( 229 | | uint256 marketTokenAmount 230 | | ) internal { 231 | * | if (marketTokenAmount == 0) { 232 | | fl.log("Withdrawal marketTokenAmount is 0"); 233 | | } 234 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) { 235 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6"); 236 | | } 237 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) { 238 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12"); 239 | | } 240 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) { 241 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18"); 242 | | } 243 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) { 244 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24"); 245 | | } 246 | * | if (marketTokenAmount > 1e24) { 247 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24"); 248 | | } 249 | | } 250 | | 251 | * | function _logWithdrawalMinLongTokenAmountCoverage_cancelWithdrawal( 252 | | uint256 minLongTokenAmount 253 | | ) internal { 254 | * | if (minLongTokenAmount == 0) { 255 | | fl.log("Withdrawal minLongTokenAmount is 0"); 256 | | } 257 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) { 258 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6"); 259 | | } 260 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) { 261 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12"); 262 | | } 263 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) { 264 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18"); 265 | | } 266 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) { 267 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24"); 268 | | } 269 | * | if (minLongTokenAmount > 1e24) { 270 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24"); 271 | | } 272 | | } 273 | | 274 | * | function _logWithdrawalMinShortTokenAmountCoverage_cancelWithdrawal( 275 | | uint256 minShortTokenAmount 276 | | ) internal { 277 | * | if (minShortTokenAmount == 0) { 278 | | fl.log("Withdrawal minShortTokenAmount is 0"); 279 | | } 280 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) { 281 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6"); 282 | | } 283 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) { 284 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12"); 285 | | } 286 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) { 287 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18"); 288 | | } 289 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) { 290 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24"); 291 | | } 292 | * | if (minShortTokenAmount > 1e24) { 293 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24"); 294 | | } 295 | | } 296 | | 297 | * | function _logWithdrawalUpdatedAtBlockCoverage_cancelWithdrawal( 298 | | uint256 updatedAtBlock 299 | | ) internal { 300 | * | if (updatedAtBlock == 0) { 301 | | fl.log("Withdrawal updatedAtBlock is 0"); 302 | | } else { 303 | * | fl.log("Withdrawal updatedAtBlock is non-zero"); 304 | | } 305 | | } 306 | | 307 | * | function _logWithdrawalUpdatedAtTimeCoverage_cancelWithdrawal( 308 | | uint256 updatedAtTime 309 | | ) internal { 310 | * | if (updatedAtTime == 0) { 311 | | fl.log("Withdrawal updatedAtTime is 0"); 312 | | } else { 313 | * | fl.log("Withdrawal updatedAtTime is non-zero"); 314 | | } 315 | | } 316 | | 317 | * | function _logWithdrawalExecutionFeeCoverage_cancelWithdrawal( 318 | | uint256 executionFee 319 | | ) internal { 320 | * | if (executionFee == 0) { 321 | * | fl.log("Withdrawal executionFee is 0"); 322 | | } 323 | * | if (executionFee > 0 && executionFee <= 1e6) { 324 | | fl.log("Withdrawal executionFee is between 0 and 1e6"); 325 | | } 326 | * | if (executionFee > 1e6 && executionFee <= 1e12) { 327 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12"); 328 | | } 329 | * | if (executionFee > 1e12 && executionFee <= 1e18) { 330 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18"); 331 | | } 332 | * | if (executionFee > 1e18 && executionFee <= 1e24) { 333 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24"); 334 | | } 335 | * | if (executionFee > 1e24) { 336 | | fl.log("Withdrawal executionFee is greater than 1e24"); 337 | | } 338 | | } 339 | | 340 | * | function _logWithdrawalCallbackGasLimitCoverage_cancelWithdrawal( 341 | | uint256 callbackGasLimit 342 | | ) internal { 343 | * | if (callbackGasLimit == 0) { 344 | | fl.log("Withdrawal callbackGasLimit is 0"); 345 | | } 346 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 347 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6"); 348 | | } 349 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 350 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12"); 351 | | } 352 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 353 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18"); 354 | | } 355 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 356 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24"); 357 | | } 358 | * | if (callbackGasLimit > 1e24) { 359 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24"); 360 | | } 361 | | } 362 | | 363 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage_cancelWithdrawal( 364 | | bool shouldUnwrapNativeToken 365 | | ) internal { 366 | * | if (shouldUnwrapNativeToken) { 367 | | fl.log("Withdrawal shouldUnwrapNativeToken is true"); 368 | | } else { 369 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false"); 370 | | } 371 | | } 372 | | } 373 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalCreatedCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract WithdrawalCreatedCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ CREATE WITHDRAWAL COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | * | function _checkCreateWithdrawalCoverage( 14 | | Withdrawal.Props memory withdrawalProps 15 | | ) internal { 16 | * | _logWithdrawalAccountCoverage(withdrawalProps.addresses.account); 17 | * | _logWithdrawalReceiverCoverage(withdrawalProps.addresses.receiver); 18 | * | _logWithdrawalCallbackContractCoverage( 19 | * | withdrawalProps.addresses.callbackContract 20 | | ); 21 | * | _logWithdrawalUiFeeReceiverCoverage( 22 | * | withdrawalProps.addresses.uiFeeReceiver 23 | | ); 24 | * | _logWithdrawalMarketCoverage(withdrawalProps.addresses.market); 25 | * | _logWithdrawalLongTokenSwapPathCoverage( 26 | * | withdrawalProps.addresses.longTokenSwapPath 27 | | ); 28 | * | _logWithdrawalShortTokenSwapPathCoverage( 29 | * | withdrawalProps.addresses.shortTokenSwapPath 30 | | ); 31 | * | _logWithdrawalMarketTokenAmountCoverage( 32 | * | withdrawalProps.numbers.marketTokenAmount 33 | | ); 34 | * | _logWithdrawalMinLongTokenAmountCoverage( 35 | * | withdrawalProps.numbers.minLongTokenAmount 36 | | ); 37 | * | _logWithdrawalMinShortTokenAmountCoverage( 38 | * | withdrawalProps.numbers.minShortTokenAmount 39 | | ); 40 | * | _logWithdrawalUpdatedAtBlockCoverage( 41 | * | withdrawalProps.numbers.updatedAtBlock 42 | | ); 43 | * | _logWithdrawalUpdatedAtTimeCoverage( 44 | * | withdrawalProps.numbers.updatedAtTime 45 | | ); 46 | * | _logWithdrawalExecutionFeeCoverage( 47 | * | withdrawalProps.numbers.executionFee 48 | | ); 49 | * | _logWithdrawalCallbackGasLimitCoverage( 50 | * | withdrawalProps.numbers.callbackGasLimit 51 | | ); 52 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage( 53 | * | withdrawalProps.flags.shouldUnwrapNativeToken 54 | | ); 55 | | } 56 | | 57 | * | function _logWithdrawalAccountCoverage(address account) internal { 58 | * | if (account == USER0) { 59 | * | fl.log("Withdrawal account USER0 hit"); 60 | | } 61 | * | if (account == USER1) { 62 | | fl.log("Withdrawal account USER1 hit"); 63 | | } 64 | * | if (account == USER2) { 65 | | fl.log("Withdrawal account USER2 hit"); 66 | | } 67 | * | if (account == USER3) { 68 | | fl.log("Withdrawal account USER3 hit"); 69 | | } 70 | * | if (account == USER4) { 71 | | fl.log("Withdrawal account USER4 hit"); 72 | | } 73 | * | if (account == USER5) { 74 | | fl.log("Withdrawal account USER5 hit"); 75 | | } 76 | * | if (account == USER6) { 77 | | fl.log("Withdrawal account USER6 hit"); 78 | | } 79 | * | if (account == USER7) { 80 | | fl.log("Withdrawal account USER7 hit"); 81 | | } 82 | * | if (account == USER8) { 83 | | fl.log("Withdrawal account USER8 hit"); 84 | | } 85 | * | if (account == USER9) { 86 | | fl.log("Withdrawal account USER9 hit"); 87 | | } 88 | * | if (account == USER10) { 89 | | fl.log("Withdrawal account USER10 hit"); 90 | | } 91 | * | if (account == USER11) { 92 | | fl.log("Withdrawal account USER11 hit"); 93 | | } 94 | * | if (account == USER12) { 95 | | fl.log("Withdrawal account USER12 hit"); 96 | | } 97 | * | if (account == USER13) { 98 | | fl.log("Withdrawal account USER13 hit"); 99 | | } 100 | | } 101 | | 102 | * | function _logWithdrawalReceiverCoverage(address receiver) internal { 103 | * | if (receiver == USER0) { 104 | * | fl.log("Withdrawal receiver USER0 hit"); 105 | | } 106 | * | if (receiver == USER1) { 107 | | fl.log("Withdrawal receiver USER1 hit"); 108 | | } 109 | * | if (receiver == USER2) { 110 | | fl.log("Withdrawal receiver USER2 hit"); 111 | | } 112 | * | if (receiver == USER3) { 113 | | fl.log("Withdrawal receiver USER3 hit"); 114 | | } 115 | * | if (receiver == USER4) { 116 | | fl.log("Withdrawal receiver USER4 hit"); 117 | | } 118 | * | if (receiver == USER5) { 119 | | fl.log("Withdrawal receiver USER5 hit"); 120 | | } 121 | * | if (receiver == USER6) { 122 | | fl.log("Withdrawal receiver USER6 hit"); 123 | | } 124 | * | if (receiver == USER7) { 125 | | fl.log("Withdrawal receiver USER7 hit"); 126 | | } 127 | * | if (receiver == USER8) { 128 | | fl.log("Withdrawal receiver USER8 hit"); 129 | | } 130 | * | if (receiver == USER9) { 131 | | fl.log("Withdrawal receiver USER9 hit"); 132 | | } 133 | * | if (receiver == USER10) { 134 | | fl.log("Withdrawal receiver USER10 hit"); 135 | | } 136 | * | if (receiver == USER11) { 137 | | fl.log("Withdrawal receiver USER11 hit"); 138 | | } 139 | * | if (receiver == USER12) { 140 | | fl.log("Withdrawal receiver USER12 hit"); 141 | | } 142 | * | if (receiver == USER13) { 143 | | fl.log("Withdrawal receiver USER13 hit"); 144 | | } 145 | | } 146 | * | function _logWithdrawalCallbackContractCoverage( 147 | | address callbackContract 148 | | ) internal { 149 | * | if (callbackContract == address(0)) { 150 | * | fl.log("Withdrawal callbackContract is address(0)"); 151 | | } else { 152 | | fl.log("Withdrawal callbackContract is non-zero address"); 153 | | } 154 | | } 155 | | 156 | * | function _logWithdrawalUiFeeReceiverCoverage( 157 | | address uiFeeReceiver 158 | | ) internal { 159 | * | if (uiFeeReceiver == address(0)) { 160 | * | fl.log("Withdrawal uiFeeReceiver is address(0)"); 161 | | } else { 162 | | fl.log("Withdrawal uiFeeReceiver is non-zero address"); 163 | | } 164 | | } 165 | | 166 | * | function _logWithdrawalMarketCoverage(address market) internal { 167 | * | if (market == address(market_0_WETH_USDC)) { 168 | * | fl.log("Withdrawal market market_0_WETH_USDC hit"); 169 | | } 170 | | 171 | * | if (market == address(market_WBTC_WBTC_USDC)) { 172 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit"); 173 | | } 174 | * | if (market == address(market_WETH_WETH_USDC)) { 175 | * | fl.log("Withdrawal market market_WETH_WETH_USDC hit"); 176 | | } 177 | * | if (market == address(market_WETH_WETH_USDT)) { 178 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit"); 179 | | } 180 | | } 181 | | 182 | * | function _logWithdrawalLongTokenSwapPathCoverage( 183 | | address[] memory longTokenSwapPath 184 | | ) internal { 185 | * | if (longTokenSwapPath.length == 0) { 186 | * | fl.log("Withdrawal longTokenSwapPath is empty"); 187 | | } 188 | * | if (longTokenSwapPath.length == 1) { 189 | | fl.log("Withdrawal longTokenSwapPath has 1 element"); 190 | | } 191 | * | if (longTokenSwapPath.length == 2) { 192 | | fl.log("Withdrawal longTokenSwapPath has 2 elements"); 193 | | } 194 | * | if (longTokenSwapPath.length >= 3) { 195 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements"); 196 | | } 197 | | } 198 | | 199 | * | function _logWithdrawalShortTokenSwapPathCoverage( 200 | | address[] memory shortTokenSwapPath 201 | | ) internal { 202 | * | if (shortTokenSwapPath.length == 0) { 203 | * | fl.log("Withdrawal shortTokenSwapPath is empty"); 204 | | } 205 | * | if (shortTokenSwapPath.length == 1) { 206 | | fl.log("Withdrawal shortTokenSwapPath has 1 element"); 207 | | } 208 | * | if (shortTokenSwapPath.length == 2) { 209 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements"); 210 | | } 211 | * | if (shortTokenSwapPath.length >= 3) { 212 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements"); 213 | | } 214 | | } 215 | | 216 | * | function _logWithdrawalMarketTokenAmountCoverage( 217 | | uint256 marketTokenAmount 218 | | ) internal { 219 | * | if (marketTokenAmount == 0) { 220 | | fl.log("Withdrawal marketTokenAmount is 0"); 221 | | } 222 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) { 223 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6"); 224 | | } 225 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) { 226 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12"); 227 | | } 228 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) { 229 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18"); 230 | | } 231 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) { 232 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24"); 233 | | } 234 | * | if (marketTokenAmount > 1e24) { 235 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24"); 236 | | } 237 | | } 238 | | 239 | * | function _logWithdrawalMinLongTokenAmountCoverage( 240 | | uint256 minLongTokenAmount 241 | | ) internal { 242 | * | if (minLongTokenAmount == 0) { 243 | | fl.log("Withdrawal minLongTokenAmount is 0"); 244 | | } 245 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) { 246 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6"); 247 | | } 248 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) { 249 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12"); 250 | | } 251 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) { 252 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18"); 253 | | } 254 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) { 255 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24"); 256 | | } 257 | * | if (minLongTokenAmount > 1e24) { 258 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24"); 259 | | } 260 | | } 261 | | 262 | * | function _logWithdrawalMinShortTokenAmountCoverage( 263 | | uint256 minShortTokenAmount 264 | | ) internal { 265 | * | if (minShortTokenAmount == 0) { 266 | | fl.log("Withdrawal minShortTokenAmount is 0"); 267 | | } 268 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) { 269 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6"); 270 | | } 271 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) { 272 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12"); 273 | | } 274 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) { 275 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18"); 276 | | } 277 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) { 278 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24"); 279 | | } 280 | * | if (minShortTokenAmount > 1e24) { 281 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24"); 282 | | } 283 | | } 284 | | 285 | * | function _logWithdrawalUpdatedAtBlockCoverage( 286 | | uint256 updatedAtBlock 287 | | ) internal { 288 | * | if (updatedAtBlock == 0) { 289 | | fl.log("Withdrawal updatedAtBlock is 0"); 290 | | } else { 291 | * | fl.log("Withdrawal updatedAtBlock is non-zero"); 292 | | } 293 | | } 294 | | 295 | * | function _logWithdrawalUpdatedAtTimeCoverage( 296 | | uint256 updatedAtTime 297 | | ) internal { 298 | * | if (updatedAtTime == 0) { 299 | | fl.log("Withdrawal updatedAtTime is 0"); 300 | | } else { 301 | * | fl.log("Withdrawal updatedAtTime is non-zero"); 302 | | } 303 | | } 304 | | 305 | * | function _logWithdrawalExecutionFeeCoverage(uint256 executionFee) internal { 306 | * | if (executionFee == 0) { 307 | * | fl.log("Withdrawal executionFee is 0"); 308 | | } 309 | * | if (executionFee > 0 && executionFee <= 1e6) { 310 | | fl.log("Withdrawal executionFee is between 0 and 1e6"); 311 | | } 312 | * | if (executionFee > 1e6 && executionFee <= 1e12) { 313 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12"); 314 | | } 315 | * | if (executionFee > 1e12 && executionFee <= 1e18) { 316 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18"); 317 | | } 318 | * | if (executionFee > 1e18 && executionFee <= 1e24) { 319 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24"); 320 | | } 321 | * | if (executionFee > 1e24) { 322 | | fl.log("Withdrawal executionFee is greater than 1e24"); 323 | | } 324 | | } 325 | | 326 | * | function _logWithdrawalCallbackGasLimitCoverage( 327 | | uint256 callbackGasLimit 328 | | ) internal { 329 | * | if (callbackGasLimit == 0) { 330 | | fl.log("Withdrawal callbackGasLimit is 0"); 331 | | } 332 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 333 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6"); 334 | | } 335 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 336 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12"); 337 | | } 338 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 339 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18"); 340 | | } 341 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 342 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24"); 343 | | } 344 | * | if (callbackGasLimit > 1e24) { 345 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24"); 346 | | } 347 | | } 348 | | 349 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage( 350 | | bool shouldUnwrapNativeToken 351 | | ) internal { 352 | * | if (shouldUnwrapNativeToken) { 353 | | fl.log("Withdrawal shouldUnwrapNativeToken is true"); 354 | | } else { 355 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false"); 356 | | } 357 | | } 358 | | } 359 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalExecuteAtomicCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract WithdrawalExecuteAtomicCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ EXECUTE ATOMIC WITHDRAWAL COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | * | function _checkExecuteAtomicWithdrawalCoverage( 13 | | Withdrawal.Props memory withdrawalProps 14 | | ) internal { 15 | * | _logWithdrawalAccountCoverage_executeAtomicWithdrawal( 16 | * | withdrawalProps.addresses.account 17 | | ); 18 | * | _logWithdrawalReceiverCoverage_executeAtomicWithdrawal( 19 | * | withdrawalProps.addresses.receiver 20 | | ); 21 | * | _logWithdrawalCallbackContractCoverage_executeAtomicWithdrawal( 22 | * | withdrawalProps.addresses.callbackContract 23 | | ); 24 | * | _logWithdrawalUiFeeReceiverCoverage_executeAtomicWithdrawal( 25 | * | withdrawalProps.addresses.uiFeeReceiver 26 | | ); 27 | * | _logWithdrawalMarketCoverage_executeAtomicWithdrawal( 28 | * | withdrawalProps.addresses.market 29 | | ); 30 | * | _logWithdrawalLongTokenSwapPathCoverage_executeAtomicWithdrawal( 31 | * | withdrawalProps.addresses.longTokenSwapPath 32 | | ); 33 | * | _logWithdrawalShortTokenSwapPathCoverage_executeAtomicWithdrawal( 34 | * | withdrawalProps.addresses.shortTokenSwapPath 35 | | ); 36 | * | _logWithdrawalMarketTokenAmountCoverage_executeAtomicWithdrawal( 37 | * | withdrawalProps.numbers.marketTokenAmount 38 | | ); 39 | * | _logWithdrawalMinLongTokenAmountCoverage_executeAtomicWithdrawal( 40 | * | withdrawalProps.numbers.minLongTokenAmount 41 | | ); 42 | * | _logWithdrawalMinShortTokenAmountCoverage_executeAtomicWithdrawal( 43 | * | withdrawalProps.numbers.minShortTokenAmount 44 | | ); 45 | * | _logWithdrawalUpdatedAtBlockCoverage_executeAtomicWithdrawal( 46 | * | withdrawalProps.numbers.updatedAtBlock 47 | | ); 48 | * | _logWithdrawalUpdatedAtTimeCoverage_executeAtomicWithdrawal( 49 | * | withdrawalProps.numbers.updatedAtTime 50 | | ); 51 | * | _logWithdrawalExecutionFeeCoverage_executeAtomicWithdrawal( 52 | * | withdrawalProps.numbers.executionFee 53 | | ); 54 | * | _logWithdrawalCallbackGasLimitCoverage_executeAtomicWithdrawal( 55 | * | withdrawalProps.numbers.callbackGasLimit 56 | | ); 57 | * | _logWithdrawalShouldUnwrapNativeTokenCoverage_executeAtomicWithdrawal( 58 | * | withdrawalProps.flags.shouldUnwrapNativeToken 59 | | ); 60 | | } 61 | | 62 | * | function _logWithdrawalAccountCoverage_executeAtomicWithdrawal( 63 | | address account 64 | | ) internal { 65 | * | if (account == USER0) { 66 | * | fl.log("Withdrawal account USER0 hit"); 67 | | } 68 | * | if (account == USER1) { 69 | | fl.log("Withdrawal account USER1 hit"); 70 | | } 71 | * | if (account == USER2) { 72 | | fl.log("Withdrawal account USER2 hit"); 73 | | } 74 | * | if (account == USER3) { 75 | | fl.log("Withdrawal account USER3 hit"); 76 | | } 77 | * | if (account == USER4) { 78 | | fl.log("Withdrawal account USER4 hit"); 79 | | } 80 | * | if (account == USER5) { 81 | | fl.log("Withdrawal account USER5 hit"); 82 | | } 83 | * | if (account == USER6) { 84 | | fl.log("Withdrawal account USER6 hit"); 85 | | } 86 | * | if (account == USER7) { 87 | | fl.log("Withdrawal account USER7 hit"); 88 | | } 89 | * | if (account == USER8) { 90 | | fl.log("Withdrawal account USER8 hit"); 91 | | } 92 | * | if (account == USER9) { 93 | | fl.log("Withdrawal account USER9 hit"); 94 | | } 95 | * | if (account == USER10) { 96 | | fl.log("Withdrawal account USER10 hit"); 97 | | } 98 | * | if (account == USER11) { 99 | | fl.log("Withdrawal account USER11 hit"); 100 | | } 101 | * | if (account == USER12) { 102 | | fl.log("Withdrawal account USER12 hit"); 103 | | } 104 | * | if (account == USER13) { 105 | | fl.log("Withdrawal account USER13 hit"); 106 | | } 107 | | } 108 | | 109 | * | function _logWithdrawalReceiverCoverage_executeAtomicWithdrawal( 110 | | address receiver 111 | | ) internal { 112 | * | if (receiver == USER0) { 113 | * | fl.log("Withdrawal receiver USER0 hit"); 114 | | } 115 | * | if (receiver == USER1) { 116 | | fl.log("Withdrawal receiver USER1 hit"); 117 | | } 118 | * | if (receiver == USER2) { 119 | | fl.log("Withdrawal receiver USER2 hit"); 120 | | } 121 | * | if (receiver == USER3) { 122 | | fl.log("Withdrawal receiver USER3 hit"); 123 | | } 124 | * | if (receiver == USER4) { 125 | | fl.log("Withdrawal receiver USER4 hit"); 126 | | } 127 | * | if (receiver == USER5) { 128 | | fl.log("Withdrawal receiver USER5 hit"); 129 | | } 130 | * | if (receiver == USER6) { 131 | | fl.log("Withdrawal receiver USER6 hit"); 132 | | } 133 | * | if (receiver == USER7) { 134 | | fl.log("Withdrawal receiver USER7 hit"); 135 | | } 136 | * | if (receiver == USER8) { 137 | | fl.log("Withdrawal receiver USER8 hit"); 138 | | } 139 | * | if (receiver == USER9) { 140 | | fl.log("Withdrawal receiver USER9 hit"); 141 | | } 142 | * | if (receiver == USER10) { 143 | | fl.log("Withdrawal receiver USER10 hit"); 144 | | } 145 | * | if (receiver == USER11) { 146 | | fl.log("Withdrawal receiver USER11 hit"); 147 | | } 148 | * | if (receiver == USER12) { 149 | | fl.log("Withdrawal receiver USER12 hit"); 150 | | } 151 | * | if (receiver == USER13) { 152 | | fl.log("Withdrawal receiver USER13 hit"); 153 | | } 154 | | } 155 | * | function _logWithdrawalCallbackContractCoverage_executeAtomicWithdrawal( 156 | | address callbackContract 157 | | ) internal { 158 | * | if (callbackContract == address(0)) { 159 | * | fl.log("Withdrawal callbackContract is address(0)"); 160 | | } else { 161 | | fl.log("Withdrawal callbackContract is non-zero address"); 162 | | } 163 | | } 164 | | 165 | * | function _logWithdrawalUiFeeReceiverCoverage_executeAtomicWithdrawal( 166 | | address uiFeeReceiver 167 | | ) internal { 168 | * | if (uiFeeReceiver == address(0)) { 169 | * | fl.log("Withdrawal uiFeeReceiver is address(0)"); 170 | | } else { 171 | | fl.log("Withdrawal uiFeeReceiver is non-zero address"); 172 | | } 173 | | } 174 | | 175 | * | function _logWithdrawalMarketCoverage_executeAtomicWithdrawal( 176 | | address market 177 | | ) internal { 178 | * | if (market == address(market_0_WETH_USDC)) { 179 | | fl.log("Withdrawal market market_0_WETH_USDC hit"); 180 | | } 181 | | 182 | * | if (market == address(market_WBTC_WBTC_USDC)) { 183 | * | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit"); 184 | | } 185 | * | if (market == address(market_WETH_WETH_USDC)) { 186 | | fl.log("Withdrawal market market_WETH_WETH_USDC hit"); 187 | | } 188 | * | if (market == address(market_WETH_WETH_USDT)) { 189 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit"); 190 | | } 191 | | } 192 | | 193 | * | function _logWithdrawalLongTokenSwapPathCoverage_executeAtomicWithdrawal( 194 | | address[] memory longTokenSwapPath 195 | | ) internal { 196 | * | if (longTokenSwapPath.length == 0) { 197 | * | fl.log("Withdrawal longTokenSwapPath is empty"); 198 | | } 199 | * | if (longTokenSwapPath.length == 1) { 200 | | fl.log("Withdrawal longTokenSwapPath has 1 element"); 201 | | } 202 | * | if (longTokenSwapPath.length == 2) { 203 | | fl.log("Withdrawal longTokenSwapPath has 2 elements"); 204 | | } 205 | * | if (longTokenSwapPath.length >= 3) { 206 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements"); 207 | | } 208 | | } 209 | | 210 | * | function _logWithdrawalShortTokenSwapPathCoverage_executeAtomicWithdrawal( 211 | | address[] memory shortTokenSwapPath 212 | | ) internal { 213 | * | if (shortTokenSwapPath.length == 0) { 214 | * | fl.log("Withdrawal shortTokenSwapPath is empty"); 215 | | } 216 | * | if (shortTokenSwapPath.length == 1) { 217 | | fl.log("Withdrawal shortTokenSwapPath has 1 element"); 218 | | } 219 | * | if (shortTokenSwapPath.length == 2) { 220 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements"); 221 | | } 222 | * | if (shortTokenSwapPath.length >= 3) { 223 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements"); 224 | | } 225 | | } 226 | | 227 | * | function _logWithdrawalMarketTokenAmountCoverage_executeAtomicWithdrawal( 228 | | uint256 marketTokenAmount 229 | | ) internal { 230 | * | if (marketTokenAmount == 0) { 231 | | fl.log("Withdrawal marketTokenAmount is 0"); 232 | | } 233 | * | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) { 234 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6"); 235 | | } 236 | * | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) { 237 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12"); 238 | | } 239 | * | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) { 240 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18"); 241 | | } 242 | * | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) { 243 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24"); 244 | | } 245 | * | if (marketTokenAmount > 1e24) { 246 | * | fl.log("Withdrawal marketTokenAmount is greater than 1e24"); 247 | | } 248 | | } 249 | | 250 | * | function _logWithdrawalMinLongTokenAmountCoverage_executeAtomicWithdrawal( 251 | | uint256 minLongTokenAmount 252 | | ) internal { 253 | * | if (minLongTokenAmount == 0) { 254 | | fl.log("Withdrawal minLongTokenAmount is 0"); 255 | | } 256 | * | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) { 257 | * | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6"); 258 | | } 259 | * | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) { 260 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12"); 261 | | } 262 | * | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) { 263 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18"); 264 | | } 265 | * | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) { 266 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24"); 267 | | } 268 | * | if (minLongTokenAmount > 1e24) { 269 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24"); 270 | | } 271 | | } 272 | | 273 | * | function _logWithdrawalMinShortTokenAmountCoverage_executeAtomicWithdrawal( 274 | | uint256 minShortTokenAmount 275 | | ) internal { 276 | * | if (minShortTokenAmount == 0) { 277 | | fl.log("Withdrawal minShortTokenAmount is 0"); 278 | | } 279 | * | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) { 280 | * | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6"); 281 | | } 282 | * | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) { 283 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12"); 284 | | } 285 | * | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) { 286 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18"); 287 | | } 288 | * | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) { 289 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24"); 290 | | } 291 | * | if (minShortTokenAmount > 1e24) { 292 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24"); 293 | | } 294 | | } 295 | | 296 | * | function _logWithdrawalUpdatedAtBlockCoverage_executeAtomicWithdrawal( 297 | | uint256 updatedAtBlock 298 | | ) internal { 299 | * | if (updatedAtBlock == 0) { 300 | | fl.log("Withdrawal updatedAtBlock is 0"); 301 | | } else { 302 | * | fl.log("Withdrawal updatedAtBlock is non-zero"); 303 | | } 304 | | } 305 | | 306 | * | function _logWithdrawalUpdatedAtTimeCoverage_executeAtomicWithdrawal( 307 | | uint256 updatedAtTime 308 | | ) internal { 309 | * | if (updatedAtTime == 0) { 310 | | fl.log("Withdrawal updatedAtTime is 0"); 311 | | } else { 312 | * | fl.log("Withdrawal updatedAtTime is non-zero"); 313 | | } 314 | | } 315 | | 316 | * | function _logWithdrawalExecutionFeeCoverage_executeAtomicWithdrawal( 317 | | uint256 executionFee 318 | | ) internal { 319 | * | if (executionFee == 0) { 320 | * | fl.log("Withdrawal executionFee is 0"); 321 | | } 322 | * | if (executionFee > 0 && executionFee <= 1e6) { 323 | | fl.log("Withdrawal executionFee is between 0 and 1e6"); 324 | | } 325 | * | if (executionFee > 1e6 && executionFee <= 1e12) { 326 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12"); 327 | | } 328 | * | if (executionFee > 1e12 && executionFee <= 1e18) { 329 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18"); 330 | | } 331 | * | if (executionFee > 1e18 && executionFee <= 1e24) { 332 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24"); 333 | | } 334 | * | if (executionFee > 1e24) { 335 | | fl.log("Withdrawal executionFee is greater than 1e24"); 336 | | } 337 | | } 338 | | 339 | * | function _logWithdrawalCallbackGasLimitCoverage_executeAtomicWithdrawal( 340 | | uint256 callbackGasLimit 341 | | ) internal { 342 | * | if (callbackGasLimit == 0) { 343 | | fl.log("Withdrawal callbackGasLimit is 0"); 344 | | } 345 | * | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 346 | * | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6"); 347 | | } 348 | * | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 349 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12"); 350 | | } 351 | * | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 352 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18"); 353 | | } 354 | * | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 355 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24"); 356 | | } 357 | * | if (callbackGasLimit > 1e24) { 358 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24"); 359 | | } 360 | | } 361 | | 362 | * | function _logWithdrawalShouldUnwrapNativeTokenCoverage_executeAtomicWithdrawal( 363 | | bool shouldUnwrapNativeToken 364 | | ) internal { 365 | * | if (shouldUnwrapNativeToken) { 366 | | fl.log("Withdrawal shouldUnwrapNativeToken is true"); 367 | | } else { 368 | * | fl.log("Withdrawal shouldUnwrapNativeToken is false"); 369 | | } 370 | | } 371 | | } 372 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/logicalCoverage/withdrawalCoverage/WithdrawalExecuteCoverage.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../../properties/BeforeAfter.sol"; 6 | | 7 | | contract WithdrawalExecuteCoverage is BeforeAfter { 8 | | // /\_/\ ___ 9 | | // = o_o =_______ \ \ EXECUTE WITHDRAWAL COVERAGE 10 | | // __^ __( \.__) ) 11 | | // (@)<_____>__(_____)____/ 12 | | 13 | | function _checkExecuteWithdrawalCoverage( 14 | | Withdrawal.Props memory withdrawalProps 15 | | ) internal { 16 | | _logWithdrawalAccountCoverage_executeWithdrawal( 17 | | withdrawalProps.addresses.account 18 | | ); 19 | | _logWithdrawalReceiverCoverage_executeWithdrawal( 20 | | withdrawalProps.addresses.receiver 21 | | ); 22 | | _logWithdrawalCallbackContractCoverage_executeWithdrawal( 23 | | withdrawalProps.addresses.callbackContract 24 | | ); 25 | | _logWithdrawalUiFeeReceiverCoverage_executeWithdrawal( 26 | | withdrawalProps.addresses.uiFeeReceiver 27 | | ); 28 | | _logWithdrawalMarketCoverage_executeWithdrawal( 29 | | withdrawalProps.addresses.market 30 | | ); 31 | | _logWithdrawalLongTokenSwapPathCoverage_executeWithdrawal( 32 | | withdrawalProps.addresses.longTokenSwapPath 33 | | ); 34 | | _logWithdrawalShortTokenSwapPathCoverage_executeWithdrawal( 35 | | withdrawalProps.addresses.shortTokenSwapPath 36 | | ); 37 | | _logWithdrawalMarketTokenAmountCoverage_executeWithdrawal( 38 | | withdrawalProps.numbers.marketTokenAmount 39 | | ); 40 | | _logWithdrawalMinLongTokenAmountCoverage_executeWithdrawal( 41 | | withdrawalProps.numbers.minLongTokenAmount 42 | | ); 43 | | _logWithdrawalMinShortTokenAmountCoverage_executeWithdrawal( 44 | | withdrawalProps.numbers.minShortTokenAmount 45 | | ); 46 | | _logWithdrawalUpdatedAtBlockCoverage_executeWithdrawal( 47 | | withdrawalProps.numbers.updatedAtBlock 48 | | ); 49 | | _logWithdrawalUpdatedAtTimeCoverage_executeWithdrawal( 50 | | withdrawalProps.numbers.updatedAtTime 51 | | ); 52 | | _logWithdrawalExecutionFeeCoverage_executeWithdrawal( 53 | | withdrawalProps.numbers.executionFee 54 | | ); 55 | | _logWithdrawalCallbackGasLimitCoverage_executeWithdrawal( 56 | | withdrawalProps.numbers.callbackGasLimit 57 | | ); 58 | | _logWithdrawalShouldUnwrapNativeTokenCoverage_executeWithdrawal( 59 | | withdrawalProps.flags.shouldUnwrapNativeToken 60 | | ); 61 | | } 62 | | 63 | | function _logWithdrawalAccountCoverage_executeWithdrawal( 64 | | address account 65 | | ) internal { 66 | | if (account == USER0) { 67 | | fl.log("Withdrawal account USER0 hit"); 68 | | } 69 | | if (account == USER1) { 70 | | fl.log("Withdrawal account USER1 hit"); 71 | | } 72 | | if (account == USER2) { 73 | | fl.log("Withdrawal account USER2 hit"); 74 | | } 75 | | if (account == USER3) { 76 | | fl.log("Withdrawal account USER3 hit"); 77 | | } 78 | | if (account == USER4) { 79 | | fl.log("Withdrawal account USER4 hit"); 80 | | } 81 | | if (account == USER5) { 82 | | fl.log("Withdrawal account USER5 hit"); 83 | | } 84 | | if (account == USER6) { 85 | | fl.log("Withdrawal account USER6 hit"); 86 | | } 87 | | if (account == USER7) { 88 | | fl.log("Withdrawal account USER7 hit"); 89 | | } 90 | | if (account == USER8) { 91 | | fl.log("Withdrawal account USER8 hit"); 92 | | } 93 | | if (account == USER9) { 94 | | fl.log("Withdrawal account USER9 hit"); 95 | | } 96 | | if (account == USER10) { 97 | | fl.log("Withdrawal account USER10 hit"); 98 | | } 99 | | if (account == USER11) { 100 | | fl.log("Withdrawal account USER11 hit"); 101 | | } 102 | | if (account == USER12) { 103 | | fl.log("Withdrawal account USER12 hit"); 104 | | } 105 | | if (account == USER13) { 106 | | fl.log("Withdrawal account USER13 hit"); 107 | | } 108 | | } 109 | | 110 | | function _logWithdrawalReceiverCoverage_executeWithdrawal( 111 | | address receiver 112 | | ) internal { 113 | | if (receiver == USER0) { 114 | | fl.log("Withdrawal receiver USER0 hit"); 115 | | } 116 | | if (receiver == USER1) { 117 | | fl.log("Withdrawal receiver USER1 hit"); 118 | | } 119 | | if (receiver == USER2) { 120 | | fl.log("Withdrawal receiver USER2 hit"); 121 | | } 122 | | if (receiver == USER3) { 123 | | fl.log("Withdrawal receiver USER3 hit"); 124 | | } 125 | | if (receiver == USER4) { 126 | | fl.log("Withdrawal receiver USER4 hit"); 127 | | } 128 | | if (receiver == USER5) { 129 | | fl.log("Withdrawal receiver USER5 hit"); 130 | | } 131 | | if (receiver == USER6) { 132 | | fl.log("Withdrawal receiver USER6 hit"); 133 | | } 134 | | if (receiver == USER7) { 135 | | fl.log("Withdrawal receiver USER7 hit"); 136 | | } 137 | | if (receiver == USER8) { 138 | | fl.log("Withdrawal receiver USER8 hit"); 139 | | } 140 | | if (receiver == USER9) { 141 | | fl.log("Withdrawal receiver USER9 hit"); 142 | | } 143 | | if (receiver == USER10) { 144 | | fl.log("Withdrawal receiver USER10 hit"); 145 | | } 146 | | if (receiver == USER11) { 147 | | fl.log("Withdrawal receiver USER11 hit"); 148 | | } 149 | | if (receiver == USER12) { 150 | | fl.log("Withdrawal receiver USER12 hit"); 151 | | } 152 | | if (receiver == USER13) { 153 | | fl.log("Withdrawal receiver USER13 hit"); 154 | | } 155 | | } 156 | | function _logWithdrawalCallbackContractCoverage_executeWithdrawal( 157 | | address callbackContract 158 | | ) internal { 159 | | if (callbackContract == address(0)) { 160 | | fl.log("Withdrawal callbackContract is address(0)"); 161 | | } else { 162 | | fl.log("Withdrawal callbackContract is non-zero address"); 163 | | } 164 | | } 165 | | 166 | | function _logWithdrawalUiFeeReceiverCoverage_executeWithdrawal( 167 | | address uiFeeReceiver 168 | | ) internal { 169 | | if (uiFeeReceiver == address(0)) { 170 | | fl.log("Withdrawal uiFeeReceiver is address(0)"); 171 | | } else { 172 | | fl.log("Withdrawal uiFeeReceiver is non-zero address"); 173 | | } 174 | | } 175 | | 176 | | function _logWithdrawalMarketCoverage_executeWithdrawal( 177 | | address market 178 | | ) internal { 179 | | if (market == address(market_0_WETH_USDC)) { 180 | | fl.log("Withdrawal market market_0_WETH_USDC hit"); 181 | | } 182 | | 183 | | if (market == address(market_WBTC_WBTC_USDC)) { 184 | | fl.log("Withdrawal market market_WBTC_WBTC_USDC hit"); 185 | | } 186 | | if (market == address(market_WETH_WETH_USDC)) { 187 | | fl.log("Withdrawal market market_WETH_WETH_USDC hit"); 188 | | } 189 | | if (market == address(market_WETH_WETH_USDT)) { 190 | | fl.log("Withdrawal market market_WETH_WETH_USDT hit"); 191 | | } 192 | | } 193 | | 194 | | function _logWithdrawalLongTokenSwapPathCoverage_executeWithdrawal( 195 | | address[] memory longTokenSwapPath 196 | | ) internal { 197 | | if (longTokenSwapPath.length == 0) { 198 | | fl.log("Withdrawal longTokenSwapPath is empty"); 199 | | } 200 | | if (longTokenSwapPath.length == 1) { 201 | | fl.log("Withdrawal longTokenSwapPath has 1 element"); 202 | | } 203 | | if (longTokenSwapPath.length == 2) { 204 | | fl.log("Withdrawal longTokenSwapPath has 2 elements"); 205 | | } 206 | | if (longTokenSwapPath.length >= 3) { 207 | | fl.log("Withdrawal longTokenSwapPath has 3 or more elements"); 208 | | } 209 | | } 210 | | 211 | | function _logWithdrawalShortTokenSwapPathCoverage_executeWithdrawal( 212 | | address[] memory shortTokenSwapPath 213 | | ) internal { 214 | | if (shortTokenSwapPath.length == 0) { 215 | | fl.log("Withdrawal shortTokenSwapPath is empty"); 216 | | } 217 | | if (shortTokenSwapPath.length == 1) { 218 | | fl.log("Withdrawal shortTokenSwapPath has 1 element"); 219 | | } 220 | | if (shortTokenSwapPath.length == 2) { 221 | | fl.log("Withdrawal shortTokenSwapPath has 2 elements"); 222 | | } 223 | | if (shortTokenSwapPath.length >= 3) { 224 | | fl.log("Withdrawal shortTokenSwapPath has 3 or more elements"); 225 | | } 226 | | } 227 | | 228 | | function _logWithdrawalMarketTokenAmountCoverage_executeWithdrawal( 229 | | uint256 marketTokenAmount 230 | | ) internal { 231 | | if (marketTokenAmount == 0) { 232 | | fl.log("Withdrawal marketTokenAmount is 0"); 233 | | } 234 | | if (marketTokenAmount > 0 && marketTokenAmount <= 1e6) { 235 | | fl.log("Withdrawal marketTokenAmount is between 0 and 1e6"); 236 | | } 237 | | if (marketTokenAmount > 1e6 && marketTokenAmount <= 1e12) { 238 | | fl.log("Withdrawal marketTokenAmount is between 1e6 and 1e12"); 239 | | } 240 | | if (marketTokenAmount > 1e12 && marketTokenAmount <= 1e18) { 241 | | fl.log("Withdrawal marketTokenAmount is between 1e12 and 1e18"); 242 | | } 243 | | if (marketTokenAmount > 1e18 && marketTokenAmount <= 1e24) { 244 | | fl.log("Withdrawal marketTokenAmount is between 1e18 and 1e24"); 245 | | } 246 | | if (marketTokenAmount > 1e24) { 247 | | fl.log("Withdrawal marketTokenAmount is greater than 1e24"); 248 | | } 249 | | } 250 | | 251 | | function _logWithdrawalMinLongTokenAmountCoverage_executeWithdrawal( 252 | | uint256 minLongTokenAmount 253 | | ) internal { 254 | | if (minLongTokenAmount == 0) { 255 | | fl.log("Withdrawal minLongTokenAmount is 0"); 256 | | } 257 | | if (minLongTokenAmount > 0 && minLongTokenAmount <= 1e6) { 258 | | fl.log("Withdrawal minLongTokenAmount is between 0 and 1e6"); 259 | | } 260 | | if (minLongTokenAmount > 1e6 && minLongTokenAmount <= 1e12) { 261 | | fl.log("Withdrawal minLongTokenAmount is between 1e6 and 1e12"); 262 | | } 263 | | if (minLongTokenAmount > 1e12 && minLongTokenAmount <= 1e18) { 264 | | fl.log("Withdrawal minLongTokenAmount is between 1e12 and 1e18"); 265 | | } 266 | | if (minLongTokenAmount > 1e18 && minLongTokenAmount <= 1e24) { 267 | | fl.log("Withdrawal minLongTokenAmount is between 1e18 and 1e24"); 268 | | } 269 | | if (minLongTokenAmount > 1e24) { 270 | | fl.log("Withdrawal minLongTokenAmount is greater than 1e24"); 271 | | } 272 | | } 273 | | 274 | | function _logWithdrawalMinShortTokenAmountCoverage_executeWithdrawal( 275 | | uint256 minShortTokenAmount 276 | | ) internal { 277 | | if (minShortTokenAmount == 0) { 278 | | fl.log("Withdrawal minShortTokenAmount is 0"); 279 | | } 280 | | if (minShortTokenAmount > 0 && minShortTokenAmount <= 1e6) { 281 | | fl.log("Withdrawal minShortTokenAmount is between 0 and 1e6"); 282 | | } 283 | | if (minShortTokenAmount > 1e6 && minShortTokenAmount <= 1e12) { 284 | | fl.log("Withdrawal minShortTokenAmount is between 1e6 and 1e12"); 285 | | } 286 | | if (minShortTokenAmount > 1e12 && minShortTokenAmount <= 1e18) { 287 | | fl.log("Withdrawal minShortTokenAmount is between 1e12 and 1e18"); 288 | | } 289 | | if (minShortTokenAmount > 1e18 && minShortTokenAmount <= 1e24) { 290 | | fl.log("Withdrawal minShortTokenAmount is between 1e18 and 1e24"); 291 | | } 292 | | if (minShortTokenAmount > 1e24) { 293 | | fl.log("Withdrawal minShortTokenAmount is greater than 1e24"); 294 | | } 295 | | } 296 | | 297 | | function _logWithdrawalUpdatedAtBlockCoverage_executeWithdrawal( 298 | | uint256 updatedAtBlock 299 | | ) internal { 300 | | if (updatedAtBlock == 0) { 301 | | fl.log("Withdrawal updatedAtBlock is 0"); 302 | | } else { 303 | | fl.log("Withdrawal updatedAtBlock is non-zero"); 304 | | } 305 | | } 306 | | 307 | | function _logWithdrawalUpdatedAtTimeCoverage_executeWithdrawal( 308 | | uint256 updatedAtTime 309 | | ) internal { 310 | | if (updatedAtTime == 0) { 311 | | fl.log("Withdrawal updatedAtTime is 0"); 312 | | } else { 313 | | fl.log("Withdrawal updatedAtTime is non-zero"); 314 | | } 315 | | } 316 | | 317 | | function _logWithdrawalExecutionFeeCoverage_executeWithdrawal( 318 | | uint256 executionFee 319 | | ) internal { 320 | | if (executionFee == 0) { 321 | | fl.log("Withdrawal executionFee is 0"); 322 | | } 323 | | if (executionFee > 0 && executionFee <= 1e6) { 324 | | fl.log("Withdrawal executionFee is between 0 and 1e6"); 325 | | } 326 | | if (executionFee > 1e6 && executionFee <= 1e12) { 327 | | fl.log("Withdrawal executionFee is between 1e6 and 1e12"); 328 | | } 329 | | if (executionFee > 1e12 && executionFee <= 1e18) { 330 | | fl.log("Withdrawal executionFee is between 1e12 and 1e18"); 331 | | } 332 | | if (executionFee > 1e18 && executionFee <= 1e24) { 333 | | fl.log("Withdrawal executionFee is between 1e18 and 1e24"); 334 | | } 335 | | if (executionFee > 1e24) { 336 | | fl.log("Withdrawal executionFee is greater than 1e24"); 337 | | } 338 | | } 339 | | 340 | | function _logWithdrawalCallbackGasLimitCoverage_executeWithdrawal( 341 | | uint256 callbackGasLimit 342 | | ) internal { 343 | | if (callbackGasLimit == 0) { 344 | | fl.log("Withdrawal callbackGasLimit is 0"); 345 | | } 346 | | if (callbackGasLimit > 0 && callbackGasLimit <= 1e6) { 347 | | fl.log("Withdrawal callbackGasLimit is between 0 and 1e6"); 348 | | } 349 | | if (callbackGasLimit > 1e6 && callbackGasLimit <= 1e12) { 350 | | fl.log("Withdrawal callbackGasLimit is between 1e6 and 1e12"); 351 | | } 352 | | if (callbackGasLimit > 1e12 && callbackGasLimit <= 1e18) { 353 | | fl.log("Withdrawal callbackGasLimit is between 1e12 and 1e18"); 354 | | } 355 | | if (callbackGasLimit > 1e18 && callbackGasLimit <= 1e24) { 356 | | fl.log("Withdrawal callbackGasLimit is between 1e18 and 1e24"); 357 | | } 358 | | if (callbackGasLimit > 1e24) { 359 | | fl.log("Withdrawal callbackGasLimit is greater than 1e24"); 360 | | } 361 | | } 362 | | 363 | | function _logWithdrawalShouldUnwrapNativeTokenCoverage_executeWithdrawal( 364 | | bool shouldUnwrapNativeToken 365 | | ) internal { 366 | | if (shouldUnwrapNativeToken) { 367 | | fl.log("Withdrawal shouldUnwrapNativeToken is true"); 368 | | } else { 369 | | fl.log("Withdrawal shouldUnwrapNativeToken is false"); 370 | | } 371 | | } 372 | | } 373 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/ChainlinkMock.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "../../contracts/oracle/IOracleProvider.sol"; 5 | | 6 | * | contract ChainlinkMock is IOracleProvider { 7 | | event TokenPriceSet(address token, uint min, uint max); 8 | | 9 | | struct TokenPrice { 10 | | uint min; 11 | | uint max; 12 | | } 13 | | 14 | | mapping(address => TokenPrice) private tokenPrices; 15 | | 16 | * | function setOraclePrice(address token, uint min, uint max, uint precisions) public { 17 | * | uint minPrice = min * (10 ** precisions); 18 | * | uint maxPrice = max * (10 ** precisions); 19 | * | tokenPrices[token] = TokenPrice(minPrice, maxPrice); 20 | * | emit TokenPriceSet(token, minPrice, maxPrice); 21 | | } 22 | * | function getOraclePrice( 23 | | address token, 24 | | bytes memory data 25 | * | ) external view returns (OracleUtils.ValidatedPrice memory) { 26 | * | TokenPrice memory tokenPrice = tokenPrices[token]; 27 | | 28 | * | return 29 | * | OracleUtils.ValidatedPrice({ 30 | * | token: token, 31 | * | min: tokenPrice.min, 32 | * | max: tokenPrice.max, 33 | * | timestamp: block.timestamp, 34 | * | provider: address(this) 35 | | }); 36 | | } 37 | | } 38 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/MockDEX.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.13; 4 | | 5 | | import {MockLP} from "./MockLP.sol"; 6 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 7 | | 8 | * | contract MockDex { 9 | | bool DEBUG = true; 10 | | 11 | | mapping(address => mapping(address => address)) public getPair; 12 | | 13 | | event PairCreated(address tokenA, address tokenB, address pair); 14 | | event LiquidityAdded( 15 | | address sender, 16 | | address tokenA, 17 | | address tokenB, 18 | | uint256 amountA, 19 | | uint256 amountB, 20 | | uint256 liquidity 21 | | ); 22 | | event LiquidityRemoved( 23 | | address sender, 24 | | address tokenA, 25 | | address tokenB, 26 | | uint256 amountA, 27 | | uint256 amountB, 28 | | uint256 liquidity 29 | | ); 30 | | event Swap( 31 | | address sender, 32 | | address tokenIn, 33 | | address tokenOut, 34 | | uint256 amountIn, 35 | | uint256 amountOut 36 | | ); 37 | | 38 | * | function getTokenTransferProxy() public view returns (address) { 39 | * | return address(this); 40 | | } 41 | | 42 | * | function createPair( 43 | | address tokenA, 44 | | address tokenB, 45 | | uint256 feePercentage, 46 | | uint256 maxSwapPercentage, 47 | | string memory name, 48 | | string memory symbol 49 | * | ) public returns (address pair) { 50 | * | require(tokenA != tokenB, "DEX: IDENTICAL_ADDRESSES"); 51 | * | require(getPair[tokenA][tokenB] == address(0), "DEX: PAIR_EXISTS"); 52 | | 53 | | pair = address( 54 | | new MockLP( 55 | | IERC20(tokenA), 56 | | IERC20(tokenB), 57 | | feePercentage, 58 | | maxSwapPercentage, 59 | | name, 60 | | symbol 61 | | ) 62 | | ); 63 | | 64 | | getPair[tokenA][tokenB] = pair; 65 | | getPair[tokenB][tokenA] = pair; 66 | | 67 | | IERC20(tokenA).approve(pair, type(uint256).max); 68 | | IERC20(tokenB).approve(pair, type(uint256).max); 69 | | 70 | | emit PairCreated(tokenA, tokenB, pair); 71 | | } 72 | | 73 | | function addLiquidity( 74 | | address tokenA, 75 | | address tokenB, 76 | | uint256 amountADesired, 77 | | uint256 amountBDesired, 78 | | uint256 amountAMin, 79 | | uint256 amountBMin 80 | | ) public { 81 | | address pair = getPair[tokenA][tokenB]; 82 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST"); 83 | | 84 | | IERC20(tokenA).transferFrom(msg.sender, address(this), amountADesired); 85 | | IERC20(tokenB).transferFrom(msg.sender, address(this), amountBDesired); 86 | | 87 | | (uint256 amountA, uint256 amountB, uint256 liquidity) = MockLP(pair) 88 | | .addLiquidity(amountADesired, amountBDesired, amountAMin); 89 | | 90 | | IERC20(tokenA).transfer(msg.sender, amountADesired - amountA); 91 | | IERC20(tokenB).transfer(msg.sender, amountBDesired - amountB); 92 | | IERC20(pair).transfer(msg.sender, liquidity); 93 | | 94 | | emit LiquidityAdded( 95 | | msg.sender, 96 | | tokenA, 97 | | tokenB, 98 | | amountA, 99 | | amountB, 100 | | liquidity 101 | | ); 102 | | } 103 | | 104 | | function removeLiquidity( 105 | | address tokenA, 106 | | address tokenB, 107 | | uint256 liquidity, 108 | | uint256 amountAMin, 109 | | uint256 amountBMin 110 | | ) public { 111 | | address pair = getPair[tokenA][tokenB]; 112 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST"); 113 | | 114 | | IERC20(pair).transferFrom(msg.sender, address(this), liquidity); 115 | | 116 | | (uint256 amountA, uint256 amountB) = MockLP(pair).removeLiquidity( 117 | | liquidity, 118 | | amountAMin, 119 | | amountBMin 120 | | ); 121 | | 122 | | IERC20(tokenA).transfer(msg.sender, amountA); 123 | | IERC20(tokenB).transfer(msg.sender, amountB); 124 | | 125 | | emit LiquidityRemoved( 126 | | msg.sender, 127 | | tokenA, 128 | | tokenB, 129 | | amountA, 130 | | amountB, 131 | | liquidity 132 | | ); 133 | | } 134 | | 135 | * | function swapExactTokensForTokens( 136 | | address tokenIn, 137 | | address tokenOut, 138 | | uint256 amountIn, 139 | | uint256 amountOutMin 140 | * | ) public { 141 | * | address pair = getPair[tokenIn][tokenOut]; 142 | * | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST"); 143 | | 144 | * | IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn); 145 | | 146 | * | uint256 amountOut = MockLP(pair).swapExactTokensForTokens( 147 | * | IERC20(tokenIn), 148 | * | IERC20(tokenOut), 149 | * | amountIn, 150 | * | amountOutMin 151 | | ); 152 | | 153 | * | IERC20(tokenOut).transfer(msg.sender, amountOut); 154 | | 155 | * | emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut); 156 | | } 157 | | 158 | | function swapTokensForExactTokens( 159 | | address tokenIn, 160 | | address tokenOut, 161 | | uint256 amountInMax, 162 | | uint256 amountOut 163 | | ) public { 164 | | address pair = getPair[tokenIn][tokenOut]; 165 | | require(pair != address(0), "DEX: PAIR_DOES_NOT_EXIST"); 166 | | 167 | | IERC20(tokenIn).transferFrom(msg.sender, address(this), amountInMax); 168 | | 169 | | uint256 amountIn = MockLP(pair).swapTokensForExactTokens( 170 | | IERC20(tokenIn), 171 | | IERC20(tokenOut), 172 | | amountInMax, 173 | | amountOut 174 | | ); 175 | | 176 | | IERC20(tokenOut).transfer(msg.sender, amountOut); 177 | | IERC20(tokenIn).transfer(msg.sender, amountInMax - amountIn); 178 | | 179 | | emit Swap(msg.sender, tokenIn, tokenOut, amountIn, amountOut); 180 | | } 181 | | } 182 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/mocks/MockLP.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.13; 4 | | 5 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 8 | | import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; 9 | | 10 | * | contract MockLP is ERC20 { 11 | | using SafeERC20 for IERC20; 12 | | 13 | | uint256 public feePercentage; 14 | | uint256 public maxSwapPercentage; 15 | | 16 | | IERC20 public tokenA; 17 | | IERC20 public tokenB; 18 | | 19 | | event Mint( 20 | | address sender, 21 | | uint256 amountA, 22 | | uint256 amountB, 23 | | uint256 liquidity 24 | | ); 25 | | event Burn( 26 | | address sender, 27 | | uint256 amountA, 28 | | uint256 amountB, 29 | | uint256 liquidity 30 | | ); 31 | | 32 | | constructor( 33 | | IERC20 _tokenA, 34 | | IERC20 _tokenB, 35 | | uint256 _feePercentage, 36 | | uint256 _maxSwapPercentage, 37 | | string memory name, 38 | | string memory symbol 39 | | ) ERC20(name, symbol) { 40 | | tokenA = _tokenA; 41 | | tokenB = _tokenB; 42 | | feePercentage = _feePercentage; 43 | | maxSwapPercentage = _maxSwapPercentage; 44 | | } 45 | | 46 | | function addLiquidity( 47 | | uint256 amountADesired, 48 | | uint256 amountBDesired, 49 | | uint256 minLiquidity 50 | | ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity) { 51 | | if (totalSupply() == 0) { 52 | | amountA = amountADesired; 53 | | amountB = amountBDesired; 54 | | liquidity = Math.sqrt(amountA * amountB); 55 | | } else { 56 | | uint256 reserveA = tokenA.balanceOf(address(this)); 57 | | uint256 reserveB = tokenB.balanceOf(address(this)); 58 | | 59 | | amountA = amountADesired; 60 | | amountB = (amountADesired * reserveB) / reserveA; 61 | | 62 | | if (amountB > amountBDesired) { 63 | | amountB = amountBDesired; 64 | | amountA = (amountB * reserveA) / reserveB; 65 | | } 66 | | 67 | | liquidity = (amountA * totalSupply()) / reserveA; 68 | | } 69 | | 70 | | require(liquidity >= minLiquidity, "Insufficient liquidity"); 71 | | 72 | | tokenA.safeTransferFrom(msg.sender, address(this), amountA); 73 | | tokenB.safeTransferFrom(msg.sender, address(this), amountB); 74 | | 75 | | _mint(msg.sender, liquidity); 76 | | 77 | | emit Mint(msg.sender, amountA, amountB, liquidity); 78 | | } 79 | | 80 | | function removeLiquidity( 81 | | uint256 liquidity, 82 | | uint256 minAmountA, 83 | | uint256 minAmountB 84 | | ) external returns (uint256 amountA, uint256 amountB) { 85 | | uint256 reserveA = tokenA.balanceOf(address(this)); 86 | | uint256 reserveB = tokenB.balanceOf(address(this)); 87 | | 88 | | amountA = (liquidity * reserveA) / totalSupply(); 89 | | amountB = (liquidity * reserveB) / totalSupply(); 90 | | 91 | | require(amountA >= minAmountA, "Insufficient amountA"); 92 | | require(amountB >= minAmountB, "Insufficient amountB"); 93 | | 94 | | _burn(msg.sender, liquidity); 95 | | 96 | | tokenA.safeTransfer(msg.sender, amountA); 97 | | tokenB.safeTransfer(msg.sender, amountB); 98 | | 99 | | emit Burn(msg.sender, amountA, amountB, liquidity); 100 | | } 101 | | 102 | * | function swapExactTokensForTokens( 103 | | IERC20 tokenIn, 104 | | IERC20 tokenOut, 105 | | uint256 amountIn, 106 | | uint256 amountOutMin 107 | * | ) external returns (uint256 amountOut) { 108 | * | uint256 reserveIn = tokenIn.balanceOf(address(this)); 109 | * | uint256 reserveOut = tokenOut.balanceOf(address(this)); 110 | | 111 | * | require( 112 | * | amountIn <= (reserveIn * maxSwapPercentage) / 100, 113 | | "Exceeds max swap percentage" 114 | | ); 115 | | 116 | * | uint256 amountInWithFee = (amountIn * (100 - feePercentage)) / 100; 117 | | 118 | * | amountOut = (amountInWithFee * reserveOut) / reserveIn; 119 | | 120 | * | require(amountOut >= amountOutMin, "Insufficient output amount"); 121 | | 122 | * | tokenIn.safeTransferFrom(msg.sender, address(this), amountIn); 123 | * | tokenOut.safeTransfer(msg.sender, amountOut); 124 | | } 125 | | 126 | | function swapTokensForExactTokens( 127 | | IERC20 tokenIn, 128 | | IERC20 tokenOut, 129 | | uint256 amountInMax, 130 | | uint256 amountOut 131 | | ) external returns (uint256 amountIn) { 132 | | uint256 reserveIn = tokenIn.balanceOf(address(this)); 133 | | uint256 reserveOut = tokenOut.balanceOf(address(this)); 134 | | 135 | | require( 136 | | amountOut <= (reserveOut * maxSwapPercentage) / 100, 137 | | "Exceeds max swap percentage" 138 | | ); 139 | | 140 | | amountIn = (amountOut * reserveIn) / reserveOut; 141 | | 142 | | amountIn = (amountIn * 100) / (100 - feePercentage); 143 | | 144 | | require(amountIn <= amountInMax, "Excessive input amount"); 145 | | 146 | | tokenIn.safeTransferFrom(msg.sender, address(this), amountIn); 147 | | tokenOut.safeTransfer(msg.sender, amountOut); 148 | | } 149 | | } 150 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/ADLProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../logicalCoverage/ADLCoverage.sol"; 6 | | 7 | | contract ADLProperties is ADLCoverage { 8 | * | function invariantPositionSizeUSDShouldDecrease( 9 | | uint positionSizeBefore, 10 | | uint positionSizeAfter, 11 | | uint reducedByDelta 12 | | ) internal { 13 | * | fl.eq( 14 | * | positionSizeBefore, 15 | * | positionSizeAfter + reducedByDelta, 16 | | "ADL-01 Position size shoud be reduced exactly by delta" 17 | | ); 18 | | } 19 | | } 20 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/BeforeAfter.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | import "../helpers/BaseSetup.sol"; 4 | | 5 | | contract BeforeAfter is BaseSetup { 6 | | error IncorrectShiftStateParams( 7 | | uint8 userIndex, 8 | | uint8 marketFromIndex, 9 | | uint8 marketToIndex, 10 | | address user, 11 | | address marketFrom, 12 | | address marketTo 13 | | ); 14 | | 15 | * | function _gammaBefore() internal { 16 | * | _snapGammaState(0); 17 | | } 18 | * | function _gammaAfter() internal { 19 | * | _snapGammaState(1); 20 | | } 21 | | 22 | * | function _snapGammaState(uint8 callNum) internal { 23 | * | _captureVaultState(callNum); 24 | * | _collectDepositInfo(callNum); 25 | | } 26 | | 27 | * | function _positionBefore() internal { 28 | * | _snapPositionState(0); 29 | | } 30 | | function _positionAfter() internal { 31 | | _snapPositionState(1); 32 | | } 33 | * | function _collectDepositInfo(uint8 stateIndex) internal { 34 | * | State storage state = states[stateIndex]; 35 | | 36 | * | for (uint i = 0; i < VAULTS.length; i++) { 37 | * | address vault = VAULTS[i]; 38 | | 39 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault]; 40 | | 41 | * | vaultInfo.totalAmount = 0; 42 | * | vaultInfo.totalSharesCalculated = 0; 43 | * | vaultInfo.oldestDepositTimestamp = type(uint256).max; 44 | * | vaultInfo.newestDepositTimestamp = 0; 45 | * | vaultInfo.collateralAmount = 0; 46 | | 47 | | //get collateral balance 48 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 49 | * | ReaderUtils.PositionInfo memory positionInfo; 50 | * | try 51 | * | reader.getPositionInfo( 52 | * | dataStore, 53 | * | referralStorage, 54 | * | PerpetualVault(vault).curPositionKey(), 55 | * | _getMarketPrices( 56 | * | vaultToMarket[vault], 57 | * | _setTokenPrices(5000e4) 58 | | ), //any price, checking for collateral 59 | * | uint256(0), 60 | * | address(0), 61 | * | true 62 | | ) 63 | * | returns (ReaderUtils.PositionInfo memory return_positionInfo) { 64 | * | positionInfo = return_positionInfo; 65 | | } catch { 66 | | // Handle the error 67 | | } 68 | * | vaultInfo.collateralAmount = positionInfo 69 | | .position 70 | | .numbers 71 | | .collateralAmount; 72 | | } 73 | | 74 | * | if (vaultInfo.totalShares > 0) { 75 | * | vaultInfo.shareValue = 76 | * | ((vaultInfo.vaultUSDCBalance + vaultInfo.collateralAmount) * 77 | * | 1e30) / 78 | * | vaultInfo.totalShares; 79 | | } else { 80 | * | vaultInfo.shareValue = 0; 81 | | } 82 | | 83 | * | for (uint j = 0; j < USERS.length; j++) { 84 | * | address user = USERS[j]; 85 | | 86 | * | UserState storage userState = vaultInfo.userStates[user]; 87 | * | userState.USDCBalance = USDC.balanceOf(USERS[j]); 88 | | 89 | * | uint256[] memory depositIds = PerpetualVault(vault) 90 | * | .getUserDeposits(user); 91 | * | userState.depositIds = depositIds; 92 | * | userState.totalAmount = 0; 93 | * | userState.totalShares = 0; 94 | * | userState.lastDepositTimestamp = 0; 95 | | 96 | * | for (uint k = 0; k < depositIds.length; k++) { 97 | * | uint256 depositId = depositIds[k]; 98 | * | DepositInfo memory deposit; 99 | * | ( 100 | * | deposit.amount, 101 | * | deposit.shares, //aaded execution fee 102 | | , 103 | | , 104 | * | deposit.timestamp, 105 | | 106 | * | ) = PerpetualVault(vault).depositInfo(depositId); 107 | * | userState.deposits[depositId] = deposit.amount; 108 | | 109 | * | userState.totalAmount += deposit.amount; 110 | * | userState.totalShares += deposit.shares; 111 | | 112 | * | if (deposit.timestamp > userState.lastDepositTimestamp) { 113 | * | userState.lastDepositTimestamp = deposit.timestamp; 114 | | } 115 | | 116 | * | vaultInfo.totalAmount += deposit.amount; 117 | * | vaultInfo.totalSharesCalculated += deposit.shares; 118 | | 119 | * | if (deposit.timestamp < vaultInfo.oldestDepositTimestamp) { 120 | * | vaultInfo.oldestDepositTimestamp = deposit.timestamp; 121 | | } 122 | * | if (deposit.timestamp > vaultInfo.newestDepositTimestamp) { 123 | * | vaultInfo.newestDepositTimestamp = deposit.timestamp; 124 | | } 125 | | } 126 | * | if (userState.totalShares > 0) { 127 | * | userState.shareValue = 128 | * | (userState.totalShares * vaultInfo.shareValue) / 129 | * | 1e30; 130 | | } else { 131 | * | userState.shareValue = 0; 132 | | } 133 | | } 134 | | } 135 | * | if (DEBUG) { 136 | | // _analyzeDepositDistribution(stateIndex); 137 | | } 138 | | } 139 | | 140 | | function _analyzeDepositDistribution(uint8 stateIndex) internal view { 141 | | State storage state = states[stateIndex]; 142 | | 143 | | for (uint i = 0; i < VAULTS.length; i++) { 144 | | address vault = VAULTS[i]; 145 | | VaultInfo storage vaultInfo = state.vaultInfos[vault]; 146 | | 147 | | for (uint j = 0; j < USERS.length; j++) { 148 | | address user = USERS[j]; 149 | | UserState storage userState = vaultInfo.userStates[user]; 150 | | uint256 userSharePercentage; 151 | | uint256 userAmountPercentage; 152 | | if ( 153 | | vaultInfo.totalSharesCalculated != 0 && 154 | | vaultInfo.totalAmount != 0 155 | | ) { 156 | | userSharePercentage = 157 | | (userState.totalShares * 1e18) / 158 | | vaultInfo.totalSharesCalculated; 159 | | userAmountPercentage = 160 | | (userState.totalAmount * 1e18) / 161 | | vaultInfo.totalAmount; 162 | | } 163 | | } 164 | | } 165 | | } 166 | | 167 | * | function _captureVaultState(uint8 stateIndex) internal { 168 | * | State storage state = states[stateIndex]; 169 | | 170 | * | for (uint i = 0; i < VAULTS.length; i++) { 171 | * | address vault = VAULTS[i]; 172 | * | PerpetualVault perpVault = PerpetualVault(vault); 173 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault]; 174 | | 175 | * | vaultInfo.totalShares = perpVault.totalShares(); 176 | * | vaultInfo.counter = perpVault.counter(); 177 | * | vaultInfo.curPositionKey = perpVault.curPositionKey(); 178 | * | vaultInfo.totalDepositAmount = perpVault.totalDepositAmount(); 179 | * | vaultInfo.beenLong = perpVault.beenLong(); 180 | * | vaultInfo.positionIsClosed = perpVault.positionIsClosed(); 181 | * | vaultInfo.gmxLock = perpVault.isLock(); 182 | * | vaultInfo.isBusy = perpVault.isBusy(); 183 | * | vaultInfo.isLocked = perpVault.isLock(); 184 | | 185 | * | vaultInfo.treasuryBalance = USDC.balanceOf(perpVault.treasury()); 186 | * | vaultInfo.vaultUSDCBalance = USDC.balanceOf(vault); 187 | | } 188 | | } 189 | * | function _snapPositionState(uint8 stateIndex) internal { 190 | | //checking for position instead of full market 191 | | //not to mix vault fees with other players in the market 192 | * | State storage state = states[stateIndex]; 193 | | 194 | * | for (uint i = 0; i < VAULTS.length; i++) { 195 | * | address vault = VAULTS[i]; 196 | * | PerpetualVault perpVault = PerpetualVault(vault); 197 | * | VaultInfo storage vaultInfo = state.vaultInfos[vault]; 198 | | 199 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 200 | * | ReaderUtils.PositionInfo memory positionInfo; 201 | * | try 202 | * | reader.getPositionInfo( 203 | * | dataStore, 204 | * | referralStorage, 205 | * | PerpetualVault(vault).curPositionKey(), 206 | * | _getMarketPrices( 207 | * | vaultToMarket[vault], 208 | * | _setTokenPrices(5000e4) 209 | | ), //any price, checking for collateral 210 | * | uint256(0), 211 | * | address(0), 212 | * | true 213 | | ) 214 | * | returns (ReaderUtils.PositionInfo memory return_positionInfo) { 215 | * | positionInfo = return_positionInfo; 216 | | } catch { 217 | | // Handle the error 218 | | } 219 | * | vaultInfo.totalFees = positionInfo 220 | | .fees 221 | | .funding 222 | | .claimableShortTokenAmount; 223 | | } 224 | | } 225 | | } 226 | * | function _snapDepositState( 227 | | address user, 228 | | address market 229 | * | ) internal returns (DepositState memory state) { 230 | * | Market.Props memory marketProps = MarketStoreUtils.get( 231 | * | dataStore, 232 | * | market 233 | | ); 234 | | 235 | * | state.userBalanceMarket = ERC20(market).balanceOf(user); 236 | * | state.vaultBalanceLong = ERC20(marketProps.longToken).balanceOf( 237 | * | address(depositVault) 238 | | ); 239 | * | state.vaultBalanceShort = ERC20(marketProps.shortToken).balanceOf( 240 | * | address(depositVault) 241 | | ); 242 | * | state.marketTotalSupply = ERC20(market).totalSupply(); 243 | | 244 | * | state.userBalanceLong = ERC20(marketProps.longToken).balanceOf(user); 245 | | 246 | * | state.userBalanceShort = ERC20(marketProps.shortToken).balanceOf(user); 247 | | } 248 | | 249 | | function _snapShiftState( 250 | | address user, 251 | | address marketFrom, 252 | | address marketTo 253 | | ) internal returns (ShiftState memory state) { 254 | | state.marketToBalance = ERC20(marketTo).balanceOf(user); 255 | | state.marketFromBalance = ERC20(marketFrom).balanceOf(user); 256 | | 257 | | Market.Props memory marketFromProps = MarketStoreUtils.get( 258 | | dataStore, 259 | | marketFrom 260 | | ); 261 | | Market.Props memory marketToProps = MarketStoreUtils.get( 262 | | dataStore, 263 | | marketTo 264 | | ); 265 | | 266 | | state.longTokenPoolAmountMarketFrom = _getPoolAmount( 267 | | dataStore, 268 | | marketFromProps, 269 | | marketFromProps.longToken 270 | | ); 271 | | 272 | | state.shortTokenPoolAmountMarketFrom = _getPoolAmount( 273 | | dataStore, 274 | | marketFromProps, 275 | | marketFromProps.shortToken 276 | | ); 277 | | 278 | | state.longTokenPoolAmountMarketTo = _getPoolAmount( 279 | | dataStore, 280 | | marketToProps, 281 | | marketToProps.longToken 282 | | ); 283 | | 284 | | state.shortTokenPoolAmountMarketTo = _getPoolAmount( 285 | | dataStore, 286 | | marketToProps, 287 | | marketToProps.shortToken 288 | | ); 289 | | 290 | | state.longTokenMarketFeeAmountMarketFrom = _getClaimableFeeAmount( 291 | | marketFrom, 292 | | marketFromProps.longToken 293 | | ); 294 | | 295 | | state.shortTokenMarketFeeAmountMarketFrom = _getClaimableFeeAmount( 296 | | marketTo, 297 | | marketFromProps.shortToken 298 | | ); 299 | | 300 | | return state; 301 | | } 302 | | 303 | | function _depositPreconditions( 304 | | uint8 userIndex, 305 | | uint8 marketIndex 306 | | ) internal { 307 | | address market = _getMarketAddress(marketIndex); 308 | | Market.Props memory marketProps = MarketStoreUtils.get( 309 | | dataStore, 310 | | market 311 | | ); 312 | | address user = _getRandomUser(userIndex); 313 | | 314 | | require( 315 | | ERC20(marketProps.marketToken).balanceOf(user) == 0, 316 | | "FuzzEchidna:: Fresh depositors only" // @coverage: limiter 317 | | ); 318 | | } 319 | | 320 | * | function _snapPositionState( 321 | | bytes32 positionKey, 322 | | OrderCreated memory order 323 | * | ) internal returns (PositionState memory) { 324 | | /* 325 | | ,___, 326 | | [O.o] 327 | | /)__) 328 | | "--" This market props are for the POSITION 329 | | NOTE: when cancelling order, position is empty 330 | | */ 331 | * | Position.Props memory position = PositionStoreUtils.get( 332 | * | dataStore, 333 | * | positionKey 334 | | ); 335 | * | Market.Props memory market = MarketStoreUtils.get( 336 | * | dataStore, 337 | * | position.addresses.market 338 | | ); 339 | | 340 | * | PositionState memory state; 341 | * | state.sizeInUsd = position.numbers.sizeInUsd; 342 | * | state.sizeInTokens = position.numbers.sizeInTokens; 343 | * | state.collateralAmount = position.numbers.collateralAmount; 344 | * | state.isLong = position.flags.isLong; 345 | * | state.OILong = dataStore.getUint( 346 | * | Keys.openInterestKey( 347 | * | order.createOrderParams.addresses.market, 348 | * | order.createOrderParams.addresses.initialCollateralToken, 349 | * | true 350 | | ) 351 | | ); 352 | | 353 | * | address lastAddress = getLastSwapPathAddress( 354 | * | order.createOrderParams.addresses 355 | | ); 356 | * | state.OILongLatestMarket = dataStore.getUint( 357 | * | Keys.openInterestKey( 358 | * | lastAddress, 359 | * | order.createOrderParams.addresses.initialCollateralToken, 360 | * | true 361 | | ) 362 | | ); 363 | | 364 | * | state.OIShort = dataStore.getUint( 365 | * | Keys.openInterestKey( 366 | * | order.createOrderParams.addresses.market, 367 | * | order.createOrderParams.addresses.initialCollateralToken, 368 | * | false 369 | | ) 370 | | ); 371 | * | state.collateralSumLong = dataStore.getUint( 372 | * | Keys.collateralSumKey( 373 | * | order.createOrderParams.addresses.market, 374 | * | order.createOrderParams.addresses.initialCollateralToken, 375 | * | true 376 | | ) 377 | | ); 378 | * | state.collateralSumShort = dataStore.getUint( 379 | * | Keys.collateralSumKey( 380 | * | order.createOrderParams.addresses.market, 381 | * | order.createOrderParams.addresses.initialCollateralToken, 382 | * | false 383 | | ) 384 | | ); 385 | | 386 | | /** 387 | | / This marketProps are for the ORDER 388 | | */ 389 | | 390 | * | Market.Props memory marketProps = MarketStoreUtils.get( 391 | * | dataStore, 392 | * | order.createOrderParams.addresses.market 393 | | ); 394 | | 395 | * | state.balanceOfLongToken = ERC20(marketProps.longToken).balanceOf( 396 | * | order.createOrderParams.addresses.receiver 397 | | ); 398 | | 399 | * | state.balanceOfShortToken = ERC20(marketProps.shortToken).balanceOf( 400 | * | order.createOrderParams.addresses.receiver 401 | | ); 402 | | 403 | * | return state; 404 | | } 405 | | 406 | * | function _snapSwapState( 407 | | bool isAfter, 408 | | OrderCreated memory order 409 | * | ) internal returns (SwapState memory) { 410 | * | SwapState memory state; 411 | | 412 | * | state.balanceOfInputToken = ERC20( 413 | * | order.createOrderParams.addresses.initialCollateralToken 414 | * | ).balanceOf(order.createOrderParams.addresses.receiver); 415 | | 416 | * | (, state.outputToken) = _getTokenOut( 417 | * | _getSwapPath(order.swapPathSeed), 418 | * | order.createOrderParams.addresses.initialCollateralToken 419 | | ); 420 | | 421 | * | state.balanceOfInputToken = ERC20( 422 | * | order.createOrderParams.addresses.initialCollateralToken 423 | * | ).balanceOf(order.createOrderParams.addresses.receiver); 424 | * | state.balanceOfOutputToken = ERC20(state.outputToken).balanceOf( 425 | * | order.createOrderParams.addresses.receiver 426 | | ); 427 | | 428 | * | if (!isAfter) { 429 | * | state.swapResult = _getAmountsOut( 430 | * | order.createOrderParams.addresses.swapPath, 431 | * | order.createOrderParams.addresses.initialCollateralToken, 432 | * | order.createOrderParams.numbers.initialCollateralDeltaAmount, 433 | * | address(0), 434 | * | order.tokenPrices 435 | | ); 436 | | } 437 | | 438 | * | if (isAfter) { 439 | * | fl.t( 440 | * | state.outputToken != address(0), 441 | | "Path should be valid at this stage" 442 | | ); 443 | | } 444 | * | return state; 445 | | } 446 | * | function getLastSwapPathAddress( 447 | | IBaseOrderUtils.CreateOrderParamsAddresses memory addresses 448 | * | ) internal pure returns (address) { 449 | * | if (addresses.swapPath.length == 0) return address(0); 450 | | uint256 lastIndex = addresses.swapPath.length - 1; 451 | | return addresses.swapPath[lastIndex]; 452 | | } 453 | | 454 | * | function _snapWithdrawalState( 455 | | address user, 456 | | address market 457 | * | ) internal returns (WithdrawalState memory withdrawalState) { 458 | * | Market.Props memory marketProps = MarketStoreUtils.get( 459 | * | dataStore, 460 | * | market 461 | | ); 462 | | 463 | * | withdrawalState.userBalance = ERC20(market).balanceOf(user); 464 | * | withdrawalState.vaultBalance = ERC20(market).balanceOf( 465 | * | address(withdrawalVault) 466 | | ); 467 | * | withdrawalState.marketTokenTotalSupply = ERC20(market).totalSupply(); 468 | * | withdrawalState.longTokenBalanceMarketVault = ERC20( 469 | * | marketProps.longToken 470 | * | ).balanceOf(market); 471 | * | withdrawalState.shortTokenBalanceMarketVault = ERC20( 472 | * | marketProps.shortToken 473 | * | ).balanceOf(market); 474 | * | withdrawalState.longTokenBalanceUser = ERC20(marketProps.longToken) 475 | * | .balanceOf(user); 476 | * | withdrawalState.nativeTokenBalanceUser = address(user).balance; 477 | * | withdrawalState.shortTokenBalanceUser = ERC20(marketProps.shortToken) 478 | * | .balanceOf(user); 479 | | } 480 | | } 481 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/DepositProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../logicalCoverage/DepositCoverage.sol"; 6 | | 7 | | contract DepositProperties is DepositCoverage { 8 | * | function invariantDepositedTokensMatchSimulatedAmounts( 9 | | DepositCreated memory depositCreated, 10 | | DepositState memory _after 11 | * | ) internal { 12 | * | uint actualDepositedAmount = _after.userBalanceMarket - 13 | * | depositCreated.beforeDepositExec.userBalanceMarket; 14 | | 15 | * | eqPercentageDiff( 16 | * | depositCreated.beforeDepositExec.simulateDepositAmountOut, 17 | * | actualDepositedAmount, 18 | * | 15e27, //eqPercentageDiff has 1e30 precision 19 | | "DEP-1 Deposited market token amount should be equal amount after simulation." 20 | | ); 21 | | } 22 | * | function invariantMarketTokenSupplyIncreases(DepositCreated memory depositCreated) internal { 23 | * | fl.gt( 24 | * | ERC20(depositCreated.createDepositParams.market).totalSupply(), 25 | * | depositCreated.beforeDepositExec.marketTotalSupply, 26 | | "DEP-2 Market tokens total supply should increase" 27 | | ); 28 | | } 29 | | 30 | | function _cancelDepositAssertions( 31 | | DepositState memory _before, 32 | | DepositState memory _after, 33 | | DepositCreated memory depositCreated 34 | | ) internal { 35 | | uint gasFeePaidForExecution = FIXED_EXECUTION_FEE_AMOUNT - address(callback).balance; 36 | | 37 | | Market.Props memory market = MarketStoreUtils.get( 38 | | dataStore, 39 | | depositCreated.createDepositParams.market 40 | | ); 41 | | 42 | | require( 43 | | market.longToken != market.shortToken, 44 | | "Assertions are not suitable for homogenic markets" 45 | | ); 46 | | 47 | | fl.eq( 48 | | _before.userBalanceMarket, 49 | | _after.userBalanceMarket, 50 | | "CNCL-DEP-01 User market token amounts should stay unchanged" 51 | | ); 52 | | 53 | | if (depositCreated.depositorParams.longAmount > 0) { 54 | | fl.lte( 55 | | _after.userBalanceLong, 56 | | _before.userBalanceLong + 57 | | depositCreated.depositorParams.longAmount + 58 | | gasFeePaidForExecution, 59 | | "CNCL-DEP-02 User long token amounts after cancel should be less or equal balance before plus deposited amount" 60 | | ); 61 | | 62 | | eqPercentageDiff( 63 | | _after.userBalanceLong, 64 | | _before.userBalanceLong + depositCreated.depositorParams.longAmount, 65 | | 1e27, //dust 66 | | "CNCL-DEP-03 User long token amounts should stay unchanged" 67 | | ); 68 | | 69 | | eqPercentageDiff( 70 | | _before.vaultBalanceLong - 71 | | depositCreated.depositorParams.longAmount - 72 | | (market.longToken == address(WETH) ? FIXED_EXECUTION_FEE_AMOUNT : 0), 73 | | //before cancel tokens are in the vault 74 | | _after.vaultBalanceLong, 75 | | 0, //exact eq 76 | | "CNCL-DEP-04 Vault long token amounts should stay unchanged" 77 | | ); 78 | | } 79 | | 80 | | if (depositCreated.depositorParams.shortAmount > 0) { 81 | | fl.lte( 82 | | _after.userBalanceShort, 83 | | _before.userBalanceShort + depositCreated.depositorParams.shortAmount, 84 | | "CNCL-DEP-05 User short token amounts after cancel should be less or equal balance before plus deposited amount" 85 | | ); 86 | | 87 | | eqPercentageDiff( 88 | | _after.userBalanceShort, 89 | | _before.userBalanceShort + depositCreated.depositorParams.shortAmount, 90 | | 1e27, //dust 91 | | "CNCL-DEP-06 User short token amounts should stay unchanged" 92 | | ); 93 | | 94 | | eqPercentageDiff( 95 | | _before.vaultBalanceShort - depositCreated.depositorParams.shortAmount, 96 | | _after.vaultBalanceShort, 97 | | 1e27, 98 | | "CNCL-DEP-07 Vault short token amounts should stay unchanged" 99 | | ); 100 | | } 101 | | } 102 | | } 103 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/LiquidationProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../logicalCoverage/LiquidationCoverage.sol"; 6 | | 7 | | contract LiquidationProperties is LiquidationCoverage { 8 | * | function invariantPositionCountShouldDecrease( 9 | | uint positionCountAfter, 10 | | uint positionCountBefore 11 | | ) internal { 12 | * | fl.lt( 13 | * | positionCountAfter, 14 | * | positionCountBefore, 15 | | "LIQ-01: Position count not decreased post-liquidation" 16 | | ); 17 | | } 18 | | 19 | * | function invariantAutoCancelListShouldBeEmptyAfterLiquidation( 20 | | uint autoCancelOrderKeysLength 21 | | ) internal { 22 | * | fl.eq( 23 | * | autoCancelOrderKeysLength, 24 | * | 0, 25 | | "LIQ-02: Auto cancel order list non-empty post-liquidation" 26 | | ); 27 | | } 28 | | 29 | * | function invariantPositionCountDecreasesByOne( 30 | | uint positionCountAfter, 31 | | uint positionCountBefore 32 | | ) internal { 33 | * | fl.eq( 34 | * | positionCountAfter + 1, 35 | * | positionCountBefore, 36 | | "LIQ-03: Position count should be decreased by 1" 37 | | ); 38 | | } 39 | | } 40 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/PositionProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "../logicalCoverage/PositionCoverage.sol"; 5 | | 6 | | contract PositionProperties is PositionCoverage { 7 | * | function _increaseAssertions( 8 | | PositionState memory _before, 9 | | PositionState memory _after, 10 | | OrderCreated memory order 11 | * | ) internal { 12 | * | uint sizeDelta = order.createOrderParams.numbers.sizeDeltaUsd; 13 | * | uint collateralDelta = order 14 | | .createOrderParams 15 | | .numbers 16 | | .initialCollateralDeltaAmount; 17 | | 18 | * | if (sizeDelta > 0) 19 | *r | require( 20 | * | _after.sizeInUsd > _before.sizeInUsd, 21 | | "INC-01: Position size usd did not increase" 22 | | ); 23 | * | if (collateralDelta > 0) 24 | * | require( 25 | * | _after.collateralAmount > _before.collateralAmount, 26 | | "INC-03: Collateral amount did not increase" 27 | | ); 28 | | } 29 | | 30 | | function _decreaseAssertions( 31 | | PositionState memory _before, 32 | | PositionState memory _after, 33 | | OrderCreated memory order 34 | | ) internal { 35 | | uint sizeDelta = order.createOrderParams.numbers.sizeDeltaUsd; 36 | | uint collateralDelta = order 37 | | .createOrderParams 38 | | .numbers 39 | | .initialCollateralDeltaAmount; 40 | | 41 | | if (sizeDelta > 0) 42 | | require( 43 | | _after.sizeInUsd < _before.sizeInUsd, 44 | | "DEC-01: Position size usd did not decrease" 45 | | ); 46 | | if (collateralDelta > 0) 47 | | require( 48 | | _after.collateralAmount < _before.collateralAmount, 49 | | "DEC-02: Collateral amount did not decrease" 50 | | ); 51 | | if (_after.sizeInUsd == 0) { 52 | | bytes32 positionKey = Position.getPositionKey( 53 | | order.createOrderParams.addresses.receiver, 54 | | order.createOrderParams.addresses.market, 55 | | order.createOrderParams.addresses.initialCollateralToken, 56 | | order.createOrderParams.isLong 57 | | ); 58 | | Position.Props memory positionAfter = PositionStoreUtils.get( 59 | | dataStore, 60 | | positionKey 61 | | ); 62 | | bytes32[] memory autoCancelOrderKeys = AutoCancelUtils 63 | | .getAutoCancelOrderKeys(dataStore, positionKey); 64 | | fl.eq( 65 | | positionAfter.numbers.sizeInUsd, 66 | | 0, 67 | | "CLOSE-01: Position still has size in USD after closing" 68 | | ); 69 | | fl.eq( 70 | | positionAfter.numbers.sizeInTokens, 71 | | 0, 72 | | "CLOSE-02: Position still has size in tokens after closing" 73 | | ); 74 | | fl.eq( 75 | | positionAfter.numbers.collateralAmount, 76 | | 0, 77 | | "CLOSE-03: Position still has collateral after closing" 78 | | ); 79 | | fl.eq( 80 | | autoCancelOrderKeys.length, 81 | | 0, 82 | | "CLOSE-04: Auto cancel order list non-empty after closing position" 83 | | ); 84 | | } 85 | | if (order.createOrderParams.isLong) { 86 | | fl.lte( 87 | | _after.OILong, 88 | | _before.OILong - sizeDelta, 89 | | "DEC-03: Long OI did not decrease" 90 | | ); 91 | | fl.lte( 92 | | _after.collateralSumLong, 93 | | _before.collateralSumLong - collateralDelta, 94 | | "DEC-04: Collateral sum long did not decrease" 95 | | ); 96 | | } else { 97 | | fl.lte( 98 | | _after.OIShort, 99 | | _before.OIShort - sizeDelta, 100 | | "DEC-03: Short OI did not decrease" 101 | | ); 102 | | 103 | | fl.lte( 104 | | _after.collateralSumShort, 105 | | _before.collateralSumShort - collateralDelta, 106 | | "DEC-04: Collateral sum short did not decrease" 107 | | ); 108 | | } 109 | | } 110 | | 111 | | function _cancelOrderAssertions( 112 | | PositionState memory _before, 113 | | PositionState memory _after, 114 | | OrderCreated memory order 115 | | ) internal { 116 | | if (order.createOrderParams.isLong) { 117 | | eqPercentageDiff( 118 | | _after.balanceOfLongToken, 119 | | _before.balanceOfLongToken + order.amountSent, 120 | | 1e28, //1% 121 | | "CNCL-ORD-1: User should receive the same amount of long tokens he sent to create an order" 122 | | ); 123 | | } else { 124 | | eqPercentageDiff( 125 | | _after.balanceOfShortToken, 126 | | _before.balanceOfShortToken + order.amountSent, 127 | | 1e28, //1% 128 | | "CNCL-ORD-2: User should receive the same amount of short tokens he sent to create an order" 129 | | ); 130 | | } 131 | | } 132 | | //NOTE: excluded in GAMMA, require next level of intergration with GMX source code changes 133 | * | function _swapAssertions( 134 | | SwapState memory _before, 135 | | SwapState memory _after, 136 | | OrderCreated memory order 137 | | ) internal { 138 | | // eqPercentageDiff( 139 | | // _after.balanceOfOutputToken, 140 | | // _before.balanceOfOutputToken + _before.swapResult.amountOut, 141 | | // 1e27, 142 | | // "SWP-01 Received token balance after swap should be equal to simulated amounts before swap." 143 | | // ); 144 | | } 145 | | } 146 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/Properties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./ShiftProperties.sol"; 6 | | import "./PositionProperties.sol"; 7 | | import "./WithdrawalProperties.sol"; 8 | | import "./DepositProperties.sol"; 9 | | import "./LiquidationProperties.sol"; 10 | | import "./ADLProperties.sol"; 11 | | 12 | | contract Properties is 13 | | ShiftProperties, 14 | | PositionProperties, 15 | | WithdrawalProperties, 16 | | DepositProperties, 17 | | LiquidationProperties, 18 | | ADLProperties 19 | | { 20 | | uint256 internal TEN_THOUSAND = 10_000; 21 | | 22 | * | function gammaGeneralPostconditions( 23 | | address vault, 24 | | uint priceSeed 25 | | ) internal { 26 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) { 27 | | //NOTE: assume successfull execution 28 | * | _invariant_GAMMA_03(vault); 29 | * | _invariant_GAMMA_04(vault); 30 | * | _invariant_GAMMA_05(vault); 31 | * | _invariant_GAMMA_06(vault, priceSeed); 32 | * | _invariant_GAMMA_09(vault); 33 | * | _invariant_GAMMA_10(vault); 34 | | } 35 | | } 36 | | 37 | * | function _invariant_GAMMA_02(address vault) internal { 38 | * | fl.eq( 39 | * | states[1].vaultInfos[vault].totalShares, 40 | * | states[1].vaultInfos[vault].totalSharesCalculated, 41 | | "GAMMA-2" 42 | | ); 43 | | } 44 | * | function _invariant_GAMMA_03(address vault) internal { 45 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) { 46 | * | VaultInfo storage vaultInfoBefore = states[0].vaultInfos[vault]; 47 | * | VaultInfo storage vaultInfoAfter = states[1].vaultInfos[vault]; 48 | | 49 | * | uint256 vaultShareValueBefore = vaultInfoBefore.shareValue; 50 | | //preventing false positives when value share % changes 51 | | //from 1wei to 1e15 by introducing arbitrary low precision treshold 52 | * | if ( 53 | * | vaultInfoBefore.vaultUSDCBalance + 54 | * | vaultInfoBefore.collateralAmount > 55 | * | 1e3 56 | * | ) { 57 | * | uint256 vaultShareValueAfter = vaultInfoAfter.shareValue; 58 | * | if (vaultShareValueAfter != 0) { 59 | * | int256 vaultShareValueChangePercentage; 60 | * | if (vaultShareValueBefore == 0) { 61 | | vaultShareValueChangePercentage = 0; 62 | * | } else { 63 | * | int256 difference = int256(vaultShareValueAfter) - 64 | * | int256(vaultShareValueBefore); 65 | * | if ( 66 | * | abs(difference) * 10000 < vaultShareValueBefore * 5 67 | | ) { 68 | | //gmx fees 69 | | // Change is less than 0.05%, consider it as no change 70 | * | vaultShareValueChangePercentage = 0; 71 | * | } else if ( 72 | * | vaultShareValueAfter >= vaultShareValueBefore 73 | | ) { 74 | * | vaultShareValueChangePercentage = int256( 75 | * | ((vaultShareValueAfter * 1e30) / 76 | * | vaultShareValueBefore) - 1e30 77 | | ); 78 | | } else { 79 | * | vaultShareValueChangePercentage = -int256( 80 | * | ((vaultShareValueBefore * 1e30) / 81 | * | vaultShareValueAfter) - 1e30 82 | | ); 83 | | } 84 | | } 85 | | 86 | * | uint256 userSharesChangedCount = 0; 87 | * | for (uint i = 0; i < USERS.length; i++) { 88 | * | address checkUser = USERS[i]; 89 | * | UserState storage userStateBefore = vaultInfoBefore 90 | * | .userStates[checkUser]; 91 | * | UserState storage userStateAfter = vaultInfoAfter 92 | * | .userStates[checkUser]; 93 | * | if ( 94 | * | userStateBefore.totalShares != 95 | * | userStateAfter.totalShares 96 | | ) { 97 | | userSharesChangedCount++; 98 | | } 99 | * | if ( 100 | * | userStateBefore.totalShares > 0 && 101 | * | userStateAfter.totalShares > 0 102 | * | ) { 103 | * | int256 userShareValueChangePercentage; 104 | * | if (userStateBefore.shareValue == 0) { 105 | | userShareValueChangePercentage = 0; 106 | * | } else { 107 | * | int256 difference = int256( 108 | * | userStateAfter.shareValue 109 | * | ) - int256(userStateBefore.shareValue); 110 | * | if ( 111 | * | abs(difference) * 10000 < 112 | * | userStateBefore.shareValue * 5 113 | | ) { 114 | | // Change is less than 0.05%, consider it as no change 115 | * | userShareValueChangePercentage = 0; 116 | * | } else if ( 117 | * | userStateAfter.shareValue >= 118 | * | userStateBefore.shareValue 119 | | ) { 120 | * | userShareValueChangePercentage = int256( 121 | * | ((userStateAfter.shareValue * 1e30) / 122 | * | userStateBefore.shareValue) - 1e30 123 | | ); 124 | | } else { 125 | * | userShareValueChangePercentage = -int256( 126 | * | ((userStateBefore.shareValue * 1e30) / 127 | * | userStateAfter.shareValue) - 1e30 128 | | ); 129 | | } 130 | | } 131 | | 132 | * | if (vaultShareValueChangePercentage > 1e28) { 133 | | //too small vault value change will not be seen on user share value change 134 | * | eqPercentageDiff( 135 | * | uint256(userShareValueChangePercentage), 136 | * | uint256(vaultShareValueChangePercentage), 137 | * | 3e27, // some presision tolerance 138 | | "GAMMA-3" 139 | | ); 140 | | } 141 | | } 142 | | } 143 | * | fl.lte( 144 | * | userSharesChangedCount, 145 | * | 1, 146 | | "GAMMA-3: Multiple users' shares changed unexpectedly" 147 | | ); 148 | | } 149 | | } 150 | | } 151 | | } 152 | * | function _invariant_GAMMA_04(address vault) internal { 153 | * | if (PerpetualVaultLens(vault).cancellationTriggered() == false) { 154 | * | (PerpetualVault.NextActionSelector selector, ) = PerpetualVault( 155 | * | vault 156 | | ).nextAction(); 157 | * | selector == PerpetualVault.NextActionSelector.NO_ACTION; 158 | * | fl.t( 159 | * | selector == PerpetualVault.NextActionSelector.NO_ACTION, 160 | | "GAMMA-4" 161 | | ); 162 | | } 163 | | } 164 | | 165 | * | function _invariant_GAMMA_05(address vault) internal { 166 | | //After all execution stages 167 | * | (uint swappedData, uint remainingData) = PerpetualVaultLens(vault) 168 | | ._getSwapProgress(); 169 | * | fl.t(swappedData == 0 && remainingData == 0, "GAMMA-5"); 170 | | } 171 | | 172 | * | function _invariant_GAMMA_06(address vault, uint priceSeed) internal { 173 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices( 174 | * | vaultToMarket[vault], 175 | * | priceSeed 176 | | ); 177 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 178 | * | (, , uint256 sizeInUsd, , , , ) = PerpetualVault(vault) 179 | * | .getPositionInfo(convertedPrices); 180 | | 181 | * | fl.neq(sizeInUsd, 0, "GAMMA-06"); 182 | | } 183 | | } 184 | | 185 | * | function _invariant_GAMMA_08(address vault, uint priceSeed) internal { 186 | * | MarketPrices memory convertedPrices = getConvertedMarketPrices( 187 | * | vaultToMarket[vault], 188 | * | priceSeed 189 | | ); 190 | * | if (PerpetualVault(vault).curPositionKey() != bytes32(0)) { 191 | * | (, , uint256 sizeInUsd, , , , ) = PerpetualVault(vault) 192 | * | .getPositionInfo(convertedPrices); 193 | | 194 | * | if (sizeInUsd != 0) { 195 | * | fl.t(!PerpetualVault(vault).positionIsClosed(), "GAMMA-08"); 196 | | } 197 | | } 198 | | } 199 | | 200 | * | function _invariant_GAMMA_09(address vault) internal { 201 | * | fl.t(uint(PerpetualVault(vault).flow()) == 0, "GAMMA-09"); 202 | | } 203 | | 204 | * | function _invariant_GAMMA_10(address vault) internal { 205 | *r | fl.t(PerpetualVaultLens(vault)._getGMXLock() == false, "GAMMA-10"); 206 | | } 207 | | 208 | * | function invariantDoesNotSilentRevert(bytes memory returnData) internal { 209 | * | fl.gte(returnData.length, 4, "GLOBAL-1 Should not silent revert"); 210 | *r | revert(toHexString(returnData)); 211 | | } 212 | | 213 | * | function _invariant_GAMMA_12(address vault, address user) internal { 214 | * | if (!PerpetualVaultLens(vault).cancellationTriggered() == false) { 215 | | fl.gt( 216 | | states[1].vaultInfos[vault].userStates[user].totalShares, 217 | | states[0].vaultInfos[vault].userStates[user].totalShares, 218 | | "GAMMA-12: If user deposits they will get a non-zero amount of shares" 219 | | ); 220 | | } 221 | | } 222 | | 223 | | function isLongOneLeverage( 224 | | bool _isLong, 225 | | uint256 _leverage 226 | | ) internal returns (bool) { 227 | | return _isLong && _leverage == TEN_THOUSAND; 228 | | } 229 | | } 230 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/ShiftProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../logicalCoverage/ShiftCoverage.sol"; 6 | | 7 | | contract ShiftProperties is ShiftCoverage { 8 | | function invariantFromAndToMarketTokenBalancesUpdated( 9 | | ShiftState memory _after, 10 | | ShiftState memory _before 11 | | ) internal { 12 | | require( 13 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket, 14 | | "Invalid invariant for the same market shifting" 15 | | ); 16 | | address marketFrom = _after.createShiftParams.fromMarket; 17 | | 18 | | uint marketFromTokenBalanceAfterShift = ERC20(marketFrom).balanceOf(_after.user); 19 | | 20 | | TokenPrices memory tokenPrices = _after.tokenPrices; 21 | | 22 | | address marketTo = _after.createShiftParams.toMarket; 23 | | Market.Props memory marketToProps = MarketStoreUtils.get(dataStore, marketTo); 24 | | 25 | | /** 26 | | __ 27 | | ( o> 28 | | /// \ @coverage:limiter 29 | | \V_/_ this is literally the second deposit 30 | | 31 | | 32 | | */ 33 | | 34 | | uint simulateDepositAmountOut = ReaderDepositUtils.getDepositAmountOut( 35 | | dataStore, 36 | | marketToProps, 37 | | _getMarketPrices(marketTo, tokenPrices), 38 | | _after.marketDataBefore.simulateLongTokenAmountWithdrawal, 39 | | _after.marketDataBefore.simulateShortTokenAmountWithdrawal, 40 | | address(0), 41 | | ISwapPricingUtils.SwapPricingType.Shift, // TwoStep, Shift, Atomic 42 | | true //includeVirtualInventoryImpact, removed in 7602ff95489fb032e4eeb59d81125d5f3d93e976 43 | | ); 44 | | 45 | | fl.lt( 46 | | marketFromTokenBalanceAfterShift, 47 | | _before.marketFromBalance, 48 | | "SHFT-1 User balance of `from` GM tokens decreases upon shift" 49 | | ); 50 | | uint marketToTokenBalanceAfterShift = ERC20(marketTo).balanceOf(_after.user); 51 | | 52 | | eqPercentageDiff( 53 | | marketToTokenBalanceAfterShift, //15 54 | | _before.marketToBalance + simulateDepositAmountOut, //30 55 | | 1e28, 56 | | "SHFT-2 User balance of to market GM += shift.marketTokenAmount()" 57 | | ); 58 | | 59 | | fl.eq( 60 | | marketFromTokenBalanceAfterShift, 61 | | _before.marketFromBalance - _after.marketTokenAmount, 62 | | "SHFT-3 User balance of from market GM -= shift.marketTokenAmount()" 63 | | ); 64 | | } 65 | | function invariantClaimableFeesUnchangedAfterShift( 66 | | ShiftState memory _after, 67 | | ShiftState memory _before 68 | | ) internal { 69 | | address marketFrom = _after.createShiftParams.fromMarket; 70 | | Market.Props memory marketFromProps = MarketStoreUtils.get(dataStore, marketFrom); 71 | | 72 | | uint longTokenMarketFeeAmountAfterMarketFrom = _getClaimableFeeAmount( 73 | | marketFrom, 74 | | marketFromProps.longToken 75 | | ); 76 | | uint shortTokenMarketFeeAmountAfterMarketFrom = _getClaimableFeeAmount( 77 | | marketFrom, 78 | | marketFromProps.shortToken 79 | | ); 80 | | 81 | | fl.eq( 82 | | _before.longTokenMarketFeeAmountMarketFrom, 83 | | longTokenMarketFeeAmountAfterMarketFrom, 84 | | "SHFT-4 Claimable fees for long token do not change upon shift." 85 | | ); 86 | | fl.eq( 87 | | _before.shortTokenMarketFeeAmountMarketFrom, 88 | | shortTokenMarketFeeAmountAfterMarketFrom, 89 | | "SHFT-5 Claimable fees for short token do not change upon shift." 90 | | ); 91 | | } 92 | | 93 | | function invariantFromMarketPoolAmountsDecrease( 94 | | ShiftState memory _after, 95 | | ShiftState memory _before 96 | | ) internal { 97 | | require( 98 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket, 99 | | "Invalid assertion for the same market shifting" 100 | | ); 101 | | 102 | | address marketFrom = _after.createShiftParams.fromMarket; 103 | | 104 | | Market.Props memory marketFromProps = MarketStoreUtils.get(dataStore, marketFrom); 105 | | 106 | | uint longTokenPoolAmountAfterMarketFrom = _getPoolAmount( 107 | | dataStore, 108 | | marketFromProps, 109 | | marketFromProps.longToken 110 | | ); 111 | | 112 | | uint shortTokenPoolAmountAfterMarketFrom = _getPoolAmount( 113 | | dataStore, 114 | | marketFromProps, 115 | | marketFromProps.shortToken 116 | | ); 117 | | 118 | | if (_after.marketDataBefore.simulateLongTokenAmountWithdrawal != 0) { 119 | | fl.lt( 120 | | longTokenPoolAmountAfterMarketFrom, 121 | | _before.longTokenPoolAmountMarketFrom, 122 | | "SHFT-6 Long token pool Amount For `from` market should decrease" 123 | | ); 124 | | } 125 | | if (_after.marketDataBefore.simulateShortTokenAmountWithdrawal != 0) { 126 | | fl.lt( 127 | | shortTokenPoolAmountAfterMarketFrom, 128 | | _before.shortTokenPoolAmountMarketFrom, 129 | | "SHFT-7 Short token Amount For `from` market should decrease" 130 | | ); 131 | | } 132 | | } 133 | | 134 | | function invariantToMarketPoolAmountsIncrease( 135 | | ShiftState memory _after, 136 | | ShiftState memory _before 137 | | ) internal { 138 | | require( 139 | | _after.createShiftParams.fromMarket != _after.createShiftParams.toMarket, 140 | | "Invalid assertion for the same market shifting" 141 | | ); 142 | | address marketTo = _after.createShiftParams.toMarket; 143 | | 144 | | Market.Props memory marketToProps = MarketStoreUtils.get(dataStore, marketTo); 145 | | 146 | | uint toMarketLongTokenPoolAmount = _getPoolAmount( 147 | | dataStore, 148 | | marketToProps, 149 | | marketToProps.longToken 150 | | ); 151 | | uint toMarketShortTokenPoolAmount = _getPoolAmount( 152 | | dataStore, 153 | | marketToProps, 154 | | marketToProps.shortToken 155 | | ); 156 | | if (_after.marketDataBefore.simulateLongTokenAmountWithdrawal != 0) { 157 | | fl.gt( 158 | | toMarketLongTokenPoolAmount, 159 | | _before.longTokenPoolAmountMarketTo, 160 | | "SHFT-8 Pool Amount For `to` market long token should increase" 161 | | ); 162 | | } 163 | | 164 | | if (_after.marketDataBefore.simulateShortTokenAmountWithdrawal != 0) { 165 | | fl.gt( 166 | | toMarketShortTokenPoolAmount, 167 | | _before.shortTokenPoolAmountMarketTo, 168 | | "SHFT-9 Pool Amount For `to` market short token should increase" 169 | | ); 170 | | } 171 | | } 172 | | 173 | | function invariantMarketTokenValuesStaySame(ShiftState memory _after) internal { 174 | | int defaultPriceForMarketToken = 1e30; 175 | | 176 | | if (_after.marketDataBefore.marketTokenPriceTo != defaultPriceForMarketToken) { 177 | | eqPercentageDiff( 178 | | uint(_after.marketDataBefore.marketTokenPriceFrom), 179 | | uint(_after.marketDataAfter.marketTokenPriceFrom), 180 | | 1e26, 181 | | "SHFT-10 Market token (GM) value for `from` market stays the same after shift execution." 182 | | ); 183 | | 184 | | eqPercentageDiff( 185 | | uint(_after.marketDataBefore.marketTokenPriceTo), 186 | | uint(_after.marketDataAfter.marketTokenPriceTo), 187 | | 1e26, 188 | | "SHFT-11 Market token (GM) value for `to` market stays the same after shift execution." 189 | | ); 190 | | } 191 | | } 192 | | 193 | | function _cancelShiftAssertions( 194 | | ShiftState memory _before, 195 | | ShiftState memory _after, 196 | | ShiftCreated memory shiftToCancel 197 | | ) internal { 198 | | eqPercentageDiff( 199 | | _after.marketFromBalance, 200 | | _before.marketFromBalance + shiftToCancel.marketTokenAmount, 201 | | 0, 202 | | "CNCL-SHFT-01 Market from received amount should be less or equal than before" 203 | | ); 204 | | fl.eq( 205 | | _after.marketToBalance, 206 | | _before.marketToBalance, 207 | | "CNCL-SHFT-02 Market to balance should stay unchanged" 208 | | ); 209 | | } 210 | | } 211 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/properties/WithdrawalProperties.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../logicalCoverage/WithdrawalCoverage.sol"; 6 | | 7 | | contract WithdrawalProperties is WithdrawalCoverage { 8 | | struct Cache { 9 | | uint256 userDepositAmount; 10 | | uint256 vaultValueBefore; 11 | | uint256 vaultValueAfter; 12 | | uint256 userBalanceBefore; 13 | | uint256 userBalanceAfter; 14 | | uint256 withdrawnAmount; 15 | | uint256 depositedAmount; 16 | | uint256 userShareBefore; 17 | | uint256 totalWithdrawn; 18 | | uint256 totalFeesBefore; 19 | | uint256 totalFeesAfter; 20 | | uint256 userFairShareOfFees; 21 | | uint256 userActualFees; 22 | | uint256 treasuryBalanceBefore; 23 | | uint256 treasuryBalanceAfter; 24 | | uint256 treasuryFees; 25 | | } 26 | | 27 | | function _invariant_GAMMA_01( 28 | | uint8 userSeed, 29 | | uint8 vaultSeed, 30 | | uint initialDepositAmount 31 | | ) internal { 32 | | Cache memory cache; 33 | | 34 | | address user = _getRandomUser(userSeed); 35 | | (address vault, , , ) = _gamma_getVault(vaultSeed); 36 | | 37 | | cache.userBalanceBefore = states[0] 38 | | .vaultInfos[vault] 39 | | .userStates[user] 40 | | .USDCBalance; 41 | | cache.userBalanceAfter = states[1] 42 | | .vaultInfos[vault] 43 | | .userStates[user] 44 | | .USDCBalance; 45 | | 46 | | cache.withdrawnAmount = 47 | | cache.userBalanceAfter - 48 | | cache.userBalanceBefore; 49 | | 50 | | cache.treasuryBalanceBefore = states[0] 51 | | .vaultInfos[vault] 52 | | .treasuryBalance; 53 | | cache.treasuryBalanceAfter = states[1] 54 | | .vaultInfos[vault] 55 | | .treasuryBalance; 56 | | cache.treasuryFees = 57 | | cache.treasuryBalanceAfter - 58 | | cache.treasuryBalanceBefore; 59 | | 60 | | cache.withdrawnAmount = cache.withdrawnAmount + cache.treasuryFees; //NOTE: we are taking fees into calculation for a fair share 61 | | 62 | | cache.depositedAmount = states[0].vaultInfos[vault].totalAmount; 63 | | 64 | | cache.userDepositAmount = initialDepositAmount; 65 | | 66 | | cache.userShareBefore = 67 | | (cache.userDepositAmount * 1e30) / 68 | | cache.depositedAmount; 69 | | 70 | | cache.totalFeesBefore = states[0].vaultInfos[vault].totalFees; 71 | | cache.totalFeesAfter = states[1].vaultInfos[vault].totalFees; 72 | | 73 | | if (cache.totalFeesBefore > 0 && cache.totalFeesAfter == 0) { 74 | | cache.userFairShareOfFees = 75 | | (cache.totalFeesBefore * cache.userShareBefore) / 76 | | 1e30; 77 | | 78 | | cache.userActualFees = 79 | | cache.withdrawnAmount - 80 | | cache.userDepositAmount; 81 | | 82 | | eqPercentageDiff( 83 | | uint256(cache.userFairShareOfFees), 84 | | uint256(cache.userActualFees), 85 | | 1e25, //super small tolerance for precision 86 | | "GAMMA-1" 87 | | ); 88 | | } 89 | | } 90 | | 91 | | function _invariant_GAMMA_07( 92 | | address vault, 93 | | uint depositTimestamp 94 | | ) internal { 95 | | fl.gte( 96 | | block.timestamp + PerpetualVault(vault).lockTime() + 1, 97 | | depositTimestamp, 98 | | "GAMMA-7" 99 | | ); 100 | | } 101 | | 102 | | function invariantWithdrawnTokensMatchSimulatedAmounts( 103 | | WithdrawalState memory _before, 104 | | WithdrawalState memory _after, 105 | | WithdrawalCreated memory withdrawalCreated 106 | | ) internal { 107 | | Market.Props memory marketProps = MarketStoreUtils.get( 108 | | dataStore, 109 | | withdrawalCreated.withdrawalParams.market 110 | | ); 111 | | if (marketProps.longToken != marketProps.shortToken) { 112 | | eqPercentageDiff( 113 | | _before.longTokenBalanceUser + 114 | | _before.simulateLongTokenAmountWithdrawal, 115 | | _after.longTokenBalanceUser, 116 | | 1e27, 117 | | "WITHD-1 Withdrawn long token amount should be equal amount after simulation." 118 | | ); 119 | | 120 | | eqPercentageDiff( 121 | | _before.shortTokenBalanceUser + 122 | | _before.simulateShortTokenAmountWithdrawal, 123 | | _after.shortTokenBalanceUser, 124 | | 1e27, 125 | | "WITHD-2 Withdrawn short token amount should be equal amount after simulation." 126 | | ); 127 | | } 128 | | } 129 | | 130 | | function invariantMarketTokenSupplyDecreases( 131 | | WithdrawalState memory _before, 132 | | WithdrawalState memory _after 133 | | ) internal { 134 | | fl.lt( 135 | | _after.marketTokenTotalSupply, 136 | | _before.marketTokenTotalSupply, 137 | | "WITH-3 Market tokens total supply should decrease" 138 | | ); 139 | | } 140 | * | function _cancelWithdrawalAssertions( 141 | | WithdrawalState memory _before, 142 | | WithdrawalState memory _after, 143 | | WithdrawalCreated memory withdrawalToCancel 144 | | ) internal { 145 | * | eqPercentageDiff( 146 | * | _after.userBalance, 147 | * | _before.userBalance + withdrawalToCancel.amount, 148 | * | 1e27, 149 | | "CNCL-WITH-1 User should receive market tokens back after cancelling withdrawal" 150 | | ); 151 | * | fl.eq( 152 | * | _after.marketTokenTotalSupply, 153 | * | _before.marketTokenTotalSupply, 154 | | "CNCL-WITH-2 Market tokens total supply should stay the same" 155 | | ); 156 | | 157 | * | eqPercentageDiff( 158 | * | _after.vaultBalance, 159 | * | _before.vaultBalance - withdrawalToCancel.amount, 160 | * | 1e27, 161 | | "CNCL-WITH-3 Vault should refund market tokens. " 162 | | ); 163 | | } 164 | | } 165 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzGMXConfig.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/FuzzUtils.sol"; 6 | | 7 | | /* 8 | | * Percentage representation: 9 | | * "50%" --> 5e29 10 | | * "1%" --> 1e28 11 | | * "0.1%" --> 1e27 12 | | * "0.01%" --> 1e26 13 | | */ 14 | | 15 | * | contract FuzzGMXConfig is FuzzUtils { 16 | | uint256 internal WETH_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000; 17 | | uint256 internal WBTC_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000; 18 | | uint256 internal USDC_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000; 19 | | uint256 internal USDT_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000; 20 | | 21 | | address internal FEE_RECEIVER = address(0); 22 | | address internal HOLDING_ADDRESS = address(0); 23 | | 24 | | uint256 internal MAX_UI_FEE_FACTOR = 50e24; 25 | | uint256 internal MAX_AUTO_CANCEL_ORDERS = 10; 26 | | uint256 internal MIN_HANDLE_EXECUTION_ERROR_GAS = 120 * 1000; 27 | | uint256 internal MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = 1000 * 1000; 28 | | uint256 internal MIN_ADDITIONAL_GAS_FOR_EXECUTION = 1000 * 1000; 29 | | uint256 internal MAX_CALLBACK_GAS_LIMIT = 2000 * 1000; 30 | | uint256 internal MAX_SWAP_PATH_LENGTH = 5; 31 | | uint256 internal MIN_COLLATERAL_USD = 1000e27; 32 | | uint256 internal MIN_POSITION_SIZE_USD = 1000e27; 33 | | 34 | | uint256 internal SWAP_FEE_RECEIVER_FACTOR = 37e28; 35 | | uint256 internal POSITION_FEE_RECEIVER_FACTOR = 0; 36 | | uint256 internal BORROWING_FEE_RECEIVER_FACTOR = 0; 37 | | 38 | | uint256 internal CLAIMABLE_COLLATERAL_TIME_DIVISOR = 3600; 39 | | 40 | | uint256 internal DEPOSIT_GAS_LIMIT = 0; 41 | | uint256 internal WITHDRAWAL_GAS_LIMIT = 0; 42 | | uint256 internal SINGLE_SWAP_GAS_LIMIT = 0; 43 | | uint256 internal INCREASE_ORDER_GAS_LIMIT = 0; 44 | | uint256 internal DECREASE_ORDER_GAS_LIMIT = 0; 45 | | uint256 internal SWAP_ORDER_GAS_LIMIT = 0; 46 | | 47 | | uint256 internal NATIVE_TOKEN_TRANSFER_GAS_LIMIT = 50000; 48 | | 49 | | uint256 internal ESTIMATED_GAS_FEE_BASE_AMOUNT = 1000000; 50 | | uint256 internal ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = 1000000; 51 | | uint256 internal EXECUTION_GAS_FEE_PER_ORACLE_PRICE = 20000; 52 | | uint256 internal EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = 2e30; 53 | | uint256 internal REFUND_EXECUTION_FEE_GAS_LIMIT = 1_000_000; 54 | | 55 | | bool internal SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = false; 56 | | uint256 internal REQUEST_EXPIRATION_TIME = 3600; 57 | | 58 | | uint256 internal MIN_ORACLE_SIGNERS = 0; 59 | | 60 | | int256 internal USDC_INIT_PRICE = 100000000; 61 | | int256 internal USDT_INIT_PRICE = 100000000; 62 | | 63 | | bool internal IS_ORACLE_PROVIDER_ENABLED = true; 64 | | bool internal IS_ATOMIC_ORACLE_PROVIDER = true; 65 | | 66 | | uint256 internal MIN_ORACLE_BLOCK_CONFIRMATIONS = 255; 67 | | uint256 internal MAX_ORACLE_TIMESTAMP_RANGE = 60; 68 | | uint256 internal MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = 5e29; 69 | | address internal CHAINLINK_PAYMENT_TOKEN = 70 | | 0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf; 71 | | 72 | | bytes32 internal ORACLE_TYPE_DEFAULT = 73 | | keccak256(abi.encode("one-percent-per-minute")); 74 | | address internal ORACLE_PROVIDER_FOR_TOKEN; 75 | | uint256 internal PRICE_FEED_MULTIPLIER = 1e46; 76 | | uint256 internal PRICE_FEED_HEARTBEAT_DURATION = 86400; 77 | | 78 | | address SOL = _getSyntheticTokenAddress("SOL"); 79 | | 80 | | bytes32 internal DEFAULT_MARKET_TYPE = keccak256(abi.encode("basic-v1")); 81 | | 82 | | uint256 internal MAX_POOL_AMOUNT_WETH = 1_000_000_000e18; 83 | | uint256 internal MAX_POOL_AMOUNT_USDC = 1_000_000_000e30; 84 | | uint256 internal MAX_POOL_AMOUNT_USDT = 1_000_000_000e30; 85 | | uint internal MAX_POOL_AMOUNT_WBTC = 1_000_000_000e18; 86 | | 87 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_WETH = 1_000_000_000_000_000e30; 88 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_WBTC = 1_000_000_000_000_000e30; 89 | | uint256 internal MAX_POOL_USD_FOR_DEPOSIT_USDC = 1_000_000_000_000_000e30; 90 | | 91 | | uint256 internal MIN_COLLATERAL_FACTOR = 1e28; 92 | | uint256 internal MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG = 93 | | 0; 94 | | uint256 internal MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT = 95 | | 0; 96 | | uint256 internal MAX_OPEN_INTEREST_LONG = 1000_000_000e30; 97 | | uint256 internal MAX_OPEN_INTEREST_SHORT = 1000_000_000e30; 98 | | uint256 internal RESERVE_FACTOR_LONG = 5e29; 99 | | uint256 internal RESERVE_FACTOR_SHORT = 5e29; 100 | | uint256 internal OPEN_INTEREST_RESERVE_FACTOR_LONG = 5e29; 101 | | uint256 internal OPEN_INTEREST_RESERVE_FACTOR_SHORT = 5e29; 102 | | 103 | | uint256 internal MAX_PNL_FACTOR_LONG = 5e29; 104 | | uint256 internal MAX_PNL_FACTOR_SHORT = 5e29; 105 | | uint256 internal MAX_PNL_FACTOR_FOR_TRADERS_LONG = 5e29; 106 | | uint256 internal MAX_PNL_FACTOR_FOR_TRADERS_SHORT = 5e29; 107 | | uint256 internal MAX_PNL_FACTOR_FOR_ADL_LONG = 45e28; 108 | | uint256 internal MAX_PNL_FACTOR_FOR_ADL_SHORT = 45e28; 109 | | uint256 internal MIN_PNL_FACTOR_AFTER_ADL_LONG = 40e28; 110 | | uint256 internal MIN_PNL_FACTOR_AFTER_ADL_SHORT = 40e28; 111 | | uint256 internal MAX_PNL_FACTOR_FOR_DEPOSITS_LONG = 60e28; 112 | | uint256 internal MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT = 60e28; //0.6 113 | | uint256 internal MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG = 30e28; 114 | | uint256 internal MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT = 30e28; 115 | | uint256 internal MARKET_TOKEN_TRANSFER_GAS_LIMIT = 200 * 1000; 116 | | uint256 internal MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = 1e28; 117 | | uint256 internal POSITION_IMPACT_FACTOR_POSITIVE = 2e28; 118 | | uint256 internal POSITION_IMPACT_FACTOR_NEGATIVE = 2e28; 119 | | 120 | | uint256 internal SWAP_FEE_FACTOR_POSITIVE_IMPACT = 5e26; //0.05% 121 | | uint256 internal SWAP_FEE_FACTOR_NEGATIVE_IMPACT = 7e26; //0.07% 122 | | uint256 internal SWAP_FEE_FACTOR_POSITIVE_IMPACT_SINGLE_TOKEN = 5e26; //0.05% 123 | | uint256 internal SWAP_FEE_FACTOR_NEGATIVE_IMPACT_SINGLE_TOKEN = 7e26; //0.07% 124 | | uint256 internal ATOMIC_SWAP_FEE_FACTOR = 2e28; //2% 125 | | 126 | | //--- funding 127 | | 128 | | uint256 internal FUNDING_FACTOR = 1e25; 129 | | uint256 internal FUNDING_EXPONENT_FACTOR = 1e30; 130 | | 131 | | uint256 internal THRESHOLD_FOR_STABLE_FUNDING = 0; // 5e28; 132 | | uint256 internal THRESHOLD_FOR_DECREASE_FUNDING = 0; //3e28; 133 | | uint256 internal FUNDING_INCREASE_FACTOR_PER_SECOND = 0; // 1e24; 134 | | uint256 internal FUNDING_DECREASE_FACTOR_PER_SECOND = 0; //2e22; 135 | | uint256 internal MIN_FUNDING_FACTOR_PER_SECOND = 1e25; //3e20 136 | | uint256 internal MAX_FUNDING_FACTOR_PER_SECOND = 1e30; //1e30; 137 | | 138 | | //--- v2.1 remediation 139 | | 140 | | uint256 internal EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = 1_000_000; 141 | | uint256 internal MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = 142 | | 5_000_000; 143 | | 144 | | //---- GAMMA 145 | | uint256 internal ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = 0; 146 | | } 147 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzSetup.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/FuzzActors.sol"; 6 | | 7 | | contract FuzzSetup is FuzzActors { 8 | | function deployment(address deployerContract) internal { 9 | | /** 10 | | * 0_0 * 11 | | * --- Deploying libraries using cryticArgs in fuzzer config --- 12 | | * 13 | | * --- DEPLOYING CONTRACTS --- 14 | | */ 15 | | 16 | | //Role 17 | | //for foundry 18 | | DEPLOYER = deployerContract; 19 | | 20 | | roleStore = new RoleStore(); 21 | | roleStore.grantRole(FOUNDRY_INITIAL_ADDRESS, Role.ROLE_ADMIN); //going from contract to EOA 22 | | roleStore.grantRole(DEPLOYER, Role.ROLE_ADMIN); //going from contract to EOA 23 | | roleStore.grantRole(HEVM_INITIAL_ADDRESS, Role.ROLE_ADMIN); //going from contract to EOA 24 | | 25 | | /** 26 | | * 0_0 * 27 | | * --- Config for roles --- 28 | | */ 29 | | 30 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.CONTROLLER); 31 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.ORDER_KEEPER); 32 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.ADL_KEEPER); 33 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.LIQUIDATION_KEEPER); 34 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.MARKET_KEEPER); 35 | | _roleChangingCall(DEPLOYER, DEPLOYER, Role.FROZEN_ORDER_KEEPER); 36 | | 37 | | _roleChangingCall( 38 | | HEVM_INITIAL_ADDRESS, 39 | | HEVM_INITIAL_ADDRESS, 40 | | Role.CONTROLLER 41 | | ); //To avoid unnesessary prank calls 42 | | _roleChangingCall( 43 | | HEVM_INITIAL_ADDRESS, 44 | | HEVM_INITIAL_ADDRESS, 45 | | Role.ORDER_KEEPER 46 | | ); 47 | | _roleChangingCall( 48 | | HEVM_INITIAL_ADDRESS, 49 | | HEVM_INITIAL_ADDRESS, 50 | | Role.ADL_KEEPER 51 | | ); 52 | | _roleChangingCall( 53 | | HEVM_INITIAL_ADDRESS, 54 | | HEVM_INITIAL_ADDRESS, 55 | | Role.LIQUIDATION_KEEPER 56 | | ); 57 | | _roleChangingCall( 58 | | HEVM_INITIAL_ADDRESS, 59 | | HEVM_INITIAL_ADDRESS, 60 | | Role.MARKET_KEEPER 61 | | ); 62 | | _roleChangingCall( 63 | | HEVM_INITIAL_ADDRESS, 64 | | HEVM_INITIAL_ADDRESS, 65 | | Role.FROZEN_ORDER_KEEPER 66 | | ); 67 | | 68 | | /** 69 | | * 0_0 * 70 | | * --- Deploy and mock tokens --- 71 | | */ 72 | | dataStore = new DataStore(roleStore); 73 | | 74 | | WETH = new WNT(); 75 | | // vm.label(address(WETH), "WETH"); 76 | | 77 | | WBTC = new MintableToken("Wrapped Bitcoin", "WBTC", 8); 78 | | // vm.label(address(WBTC), "WBTC"); 79 | | 80 | | USDC = new MintableToken("USD Circle", "USDC", 6); 81 | | // vm.label(address(USDC), "USDC"); 82 | | 83 | | USDT = new MintableToken("USD Tether", "USDT", 6); 84 | | // vm.label(address(USDT), "USDT"); 85 | | 86 | | /** 87 | | * 0_0 * 88 | | * --- Configure Data Store --- 89 | | */ 90 | | _setUintDataStoreCall( 91 | | DEPLOYER, 92 | | "TOKEN_TRANSFER_GAS_LIMIT", 93 | | WETH_TOKEN_TRANSFER_GAS_LIMIT, 94 | | address(WETH) 95 | | ); 96 | | _setUintDataStoreCall( 97 | | DEPLOYER, 98 | | "TOKEN_TRANSFER_GAS_LIMIT", 99 | | WBTC_TOKEN_TRANSFER_GAS_LIMIT, 100 | | address(WBTC) 101 | | ); 102 | | _setUintDataStoreCall( 103 | | DEPLOYER, 104 | | "TOKEN_TRANSFER_GAS_LIMIT", 105 | | USDC_TOKEN_TRANSFER_GAS_LIMIT, 106 | | address(USDC) 107 | | ); 108 | | _setUintDataStoreCall( 109 | | DEPLOYER, 110 | | "TOKEN_TRANSFER_GAS_LIMIT", 111 | | USDT_TOKEN_TRANSFER_GAS_LIMIT, 112 | | address(USDT) 113 | | ); 114 | | 115 | | _setAddressDataStoreCall(DEPLOYER, "WNT", address(WETH), address(0)); 116 | | _setAddressDataStoreCall( 117 | | DEPLOYER, 118 | | "FEE_RECEIVER", 119 | | address(0), 120 | | address(0) 121 | | ); 122 | | _setAddressDataStoreCall( 123 | | DEPLOYER, 124 | | "HOLDING_ADDRESS", 125 | | address(0), 126 | | address(0) 127 | | ); 128 | | 129 | | _setUintDataStoreCall( 130 | | DEPLOYER, 131 | | "MAX_UI_FEE_FACTOR", 132 | | MAX_UI_FEE_FACTOR, 133 | | address(0) 134 | | ); 135 | | _setUintDataStoreCall( 136 | | DEPLOYER, 137 | | "MAX_AUTO_CANCEL_ORDERS", 138 | | MAX_AUTO_CANCEL_ORDERS, 139 | | address(0) 140 | | ); 141 | | _setUintDataStoreCall( 142 | | DEPLOYER, 143 | | "MIN_HANDLE_EXECUTION_ERROR_GAS", 144 | | MIN_HANDLE_EXECUTION_ERROR_GAS, 145 | | address(0) 146 | | ); 147 | | _setUintDataStoreCall( 148 | | DEPLOYER, 149 | | "MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD", 150 | | MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD, 151 | | address(0) 152 | | ); 153 | | 154 | | _setUintDataStoreCall( 155 | | DEPLOYER, 156 | | "MIN_ADDITIONAL_GAS_FOR_EXECUTION", 157 | | MIN_ADDITIONAL_GAS_FOR_EXECUTION, 158 | | address(0) 159 | | ); 160 | | _setUintDataStoreCall( 161 | | DEPLOYER, 162 | | "MAX_CALLBACK_GAS_LIMIT", 163 | | MAX_CALLBACK_GAS_LIMIT, 164 | | address(0) 165 | | ); 166 | | _setUintDataStoreCall( 167 | | DEPLOYER, 168 | | "MAX_SWAP_PATH_LENGTH", 169 | | MAX_SWAP_PATH_LENGTH, 170 | | address(0) 171 | | ); 172 | | _setUintDataStoreCall( 173 | | DEPLOYER, 174 | | "MIN_COLLATERAL_USD", 175 | | MIN_COLLATERAL_USD, 176 | | address(0) 177 | | ); 178 | | _setUintDataStoreCall( 179 | | DEPLOYER, 180 | | "MIN_POSITION_SIZE_USD", 181 | | MIN_POSITION_SIZE_USD, 182 | | address(0) 183 | | ); 184 | | _setUintDataStoreCall( 185 | | DEPLOYER, 186 | | "SWAP_FEE_RECEIVER_FACTOR", 187 | | SWAP_FEE_RECEIVER_FACTOR, 188 | | address(0) 189 | | ); 190 | | _setUintDataStoreCall( 191 | | DEPLOYER, 192 | | "POSITION_FEE_RECEIVER_FACTOR", 193 | | POSITION_FEE_RECEIVER_FACTOR, 194 | | address(0) 195 | | ); 196 | | _setUintDataStoreCall( 197 | | DEPLOYER, 198 | | "CLAIMABLE_COLLATERAL_TIME_DIVISOR", 199 | | CLAIMABLE_COLLATERAL_TIME_DIVISOR, 200 | | address(0) 201 | | ); 202 | | _setUintWithBoolDataStoreCall( 203 | | DEPLOYER, 204 | | "DEPOSIT_GAS_LIMIT", 205 | | DEPOSIT_GAS_LIMIT, 206 | | true 207 | | ); 208 | | _setUintWithBoolDataStoreCall( 209 | | DEPLOYER, 210 | | "DEPOSIT_GAS_LIMIT", 211 | | DEPOSIT_GAS_LIMIT, 212 | | false 213 | | ); 214 | | _setUintDataStoreCall( 215 | | DEPLOYER, 216 | | "WITHDRAWAL_GAS_LIMIT", 217 | | WITHDRAWAL_GAS_LIMIT, 218 | | address(0) 219 | | ); 220 | | _setUintDataStoreCall( 221 | | DEPLOYER, 222 | | "SINGLE_SWAP_GAS_LIMIT", 223 | | SINGLE_SWAP_GAS_LIMIT, 224 | | address(0) 225 | | ); 226 | | _setUintDataStoreCall( 227 | | DEPLOYER, 228 | | "INCREASE_ORDER_GAS_LIMIT", 229 | | INCREASE_ORDER_GAS_LIMIT, 230 | | address(0) 231 | | ); 232 | | _setUintDataStoreCall( 233 | | DEPLOYER, 234 | | "DECREASE_ORDER_GAS_LIMIT", 235 | | DECREASE_ORDER_GAS_LIMIT, 236 | | address(0) 237 | | ); 238 | | _setUintDataStoreCall( 239 | | DEPLOYER, 240 | | "SWAP_ORDER_GAS_LIMIT", 241 | | SWAP_ORDER_GAS_LIMIT, 242 | | address(0) 243 | | ); 244 | | _setUintDataStoreCall( 245 | | DEPLOYER, 246 | | "NATIVE_TOKEN_TRANSFER_GAS_LIMIT", 247 | | NATIVE_TOKEN_TRANSFER_GAS_LIMIT, 248 | | address(0) 249 | | ); 250 | | _setUintDataStoreCall( 251 | | DEPLOYER, 252 | | "ESTIMATED_GAS_FEE_BASE_AMOUNT", 253 | | ESTIMATED_GAS_FEE_BASE_AMOUNT, 254 | | address(0) 255 | | ); 256 | | _setUintDataStoreCall( 257 | | DEPLOYER, 258 | | "ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1", 259 | | ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1, 260 | | address(0) 261 | | ); 262 | | _setUintDataStoreCall( 263 | | DEPLOYER, 264 | | "EXECUTION_GAS_FEE_MULTIPLIER_FACTOR", 265 | | EXECUTION_GAS_FEE_MULTIPLIER_FACTOR, 266 | | address(0) 267 | | ); 268 | | 269 | | _setUintDataStoreCall( 270 | | DEPLOYER, 271 | | "REFUND_EXECUTION_FEE_GAS_LIMIT", 272 | | REFUND_EXECUTION_FEE_GAS_LIMIT, 273 | | address(0) 274 | | ); 275 | | 276 | | _setUintDataStoreCall( 277 | | DEPLOYER, 278 | | "EXECUTION_GAS_FEE_PER_ORACLE_PRICE", 279 | | EXECUTION_GAS_FEE_PER_ORACLE_PRICE, 280 | | address(0) 281 | | ); 282 | | 283 | | _setBoolDataStoreCall( 284 | | DEPLOYER, 285 | | "SKIP_BORROWING_FEE_FOR_SMALLER_SIDE", 286 | | SKIP_BORROWING_FEE_FOR_SMALLER_SIDE, 287 | | address(0) 288 | | ); 289 | | _setUintDataStoreCall( 290 | | DEPLOYER, 291 | | "REQUEST_EXPIRATION_TIME", 292 | | REQUEST_EXPIRATION_TIME, 293 | | address(0) 294 | | ); 295 | | _setUintDataStoreCall( 296 | | DEPLOYER, 297 | | "ESTIMATED_GAS_FEE_PER_ORACLE_PRICE", 298 | | ESTIMATED_GAS_FEE_PER_ORACLE_PRICE, 299 | | address(0) 300 | | ); 301 | | /** 302 | | * 0_0 * 303 | | * --- Setup Timelock Controller --- 304 | | */ 305 | | govTimelockController = new GovTimelockController( 306 | | "GovTimelockController", //name 307 | | 5 * 24 * 60 * 60, // minDelay 308 | | USERS, //proposer 309 | | USERS, //executor 310 | | DEPLOYER //admin 311 | | ); 312 | | 313 | | bytes32 PROPOSER_ROLE = govTimelockController.PROPOSER_ROLE(); 314 | | vm.prank(DEPLOYER); 315 | | govTimelockController.grantRole( 316 | | PROPOSER_ROLE, 317 | | address(protocolGovernor) 318 | | ); 319 | | 320 | | bytes32 CANCELLER_ROLE = govTimelockController.CANCELLER_ROLE(); 321 | | vm.prank(DEPLOYER); 322 | | govTimelockController.grantRole( 323 | | CANCELLER_ROLE, 324 | | address(protocolGovernor) 325 | | ); 326 | | 327 | | bytes32 EXECUTOR_ROLE = govTimelockController.EXECUTOR_ROLE(); 328 | | vm.prank(DEPLOYER); 329 | | govTimelockController.grantRole( 330 | | EXECUTOR_ROLE, 331 | | address(protocolGovernor) 332 | | ); 333 | | 334 | | // bytes32 TIMELOCK_ADMIN_ROLE = govTimelockController.TIMELOCK_ADMIN_ROLE(); 335 | | // vm.prank(DEPLOYER); 336 | | // govTimelockController.revokeRole(TIMELOCK_ADMIN_ROLE, DEPLOYER); 337 | | 338 | | /** 339 | | * 0_0 * 340 | | * --- Deploy gov contracts --- 341 | | */ 342 | | govToken = new GovToken( 343 | | roleStore, 344 | | "GMX DAO", // name 345 | | "GMX_DAO", // symbol 346 | | 18 347 | | ); // decimals 348 | | 349 | | //@dev all values from ProtocolGovenor.ts test file, 350 | | //@dev test file have much smaller proposalTreshold 351 | | /** 352 | | * values from deployProtocolGovernor.ts 353 | | * return [ 354 | | * dependencyContracts.GovToken.address, // token 355 | | * dependencyContracts.GovTimelockController.address, // timelock 356 | | * "GMX Governor", // name 357 | | * "v2.0", // version 358 | | * 24 * 60 * 60, // votingDelay 359 | | * 5 * 24 * 60 * 60, // votingPeriod 360 | | * expandDecimals(30_000, 18), // proposalThreshold 361 | | * 3, // quorumNumeratorValue 362 | | * ]; 363 | | */ 364 | | protocolGovernor = new ProtocolGovernor( 365 | | govToken, 366 | | govTimelockController, // timelock 367 | | "Governor", // name 368 | | "v1", // version 369 | | 24 * 60 * 60, // votingDelay 370 | | 6 * 24 * 60 * 60, // votingPeriod 371 | | 50_000, // proposalThreshold 372 | | 4 // quorumNumeratorValue); 373 | | ); 374 | | 375 | | eventEmitter = new EventEmitter(roleStore); 376 | | 377 | | /** 378 | | * 0_0 * 379 | | * --- Oracle setup --- 380 | | */ 381 | | oracleStore = new OracleStore(roleStore, eventEmitter); 382 | | _roleChangingCall(DEPLOYER, address(oracleStore), Role.CONTROLLER); 383 | | 384 | | _oracleAddSignerCall(DEPLOYER, USER4); 385 | | _oracleAddSignerCall(DEPLOYER, USER5); 386 | | _oracleAddSignerCall(DEPLOYER, USER6); 387 | | _oracleAddSignerCall(DEPLOYER, USER7); 388 | | _oracleAddSignerCall(DEPLOYER, USER8); 389 | | _oracleAddSignerCall(DEPLOYER, USER9); 390 | | _oracleAddSignerCall(DEPLOYER, USER10); 391 | | _oracleAddSignerCall(DEPLOYER, USER11); 392 | | _oracleAddSignerCall(DEPLOYER, USER12); 393 | | _oracleAddSignerCall(DEPLOYER, USER13); 394 | | 395 | | _setUintDataStoreCall( 396 | | DEPLOYER, 397 | | "MIN_ORACLE_SIGNERS", 398 | | MIN_ORACLE_SIGNERS, 399 | | address(0) 400 | | ); 401 | | 402 | | USDCPriceFeed = new MockPriceFeed(); 403 | | USDCPriceFeed.setAnswer(USDC_INIT_PRICE); 404 | | 405 | | USDTPriceFeed = new MockPriceFeed(); 406 | | USDTPriceFeed.setAnswer(USDT_INIT_PRICE); 407 | | 408 | | gmOracleProvider = new GmOracleProvider( 409 | | roleStore, 410 | | dataStore, 411 | | oracleStore 412 | | ); 413 | | 414 | | chainlinkMock = new ChainlinkMock(); 415 | | 416 | | _setBoolDataStoreCall( 417 | | DEPLOYER, 418 | | "IS_ORACLE_PROVIDER_ENABLED", 419 | | IS_ORACLE_PROVIDER_ENABLED, 420 | | address(0) 421 | | ); 422 | | 423 | | mockDataStreamVerifier = new MockDataStreamVerifier(); 424 | | chainlinkPriceFeedProvider = new ChainlinkPriceFeedProvider(dataStore); 425 | | 426 | | _setBoolDataStoreCall( 427 | | DEPLOYER, 428 | | "IS_ORACLE_PROVIDER_ENABLED", 429 | | IS_ORACLE_PROVIDER_ENABLED, 430 | | address(chainlinkPriceFeedProvider) 431 | | ); 432 | | _setBoolDataStoreCall( 433 | | DEPLOYER, 434 | | "IS_ATOMIC_ORACLE_PROVIDER", 435 | | IS_ATOMIC_ORACLE_PROVIDER, 436 | | address(chainlinkPriceFeedProvider) 437 | | ); 438 | | 439 | | _setBoolDataStoreCall( 440 | | DEPLOYER, 441 | | "IS_ORACLE_PROVIDER_ENABLED", 442 | | IS_ORACLE_PROVIDER_ENABLED, 443 | | address(chainlinkMock) 444 | | ); 445 | | _setBoolDataStoreCall( 446 | | DEPLOYER, 447 | | "IS_ATOMIC_ORACLE_PROVIDER", 448 | | IS_ATOMIC_ORACLE_PROVIDER, 449 | | address(chainlinkMock) 450 | | ); 451 | | 452 | | oracle = new Oracle( 453 | | roleStore, 454 | | dataStore, 455 | | eventEmitter, 456 | | AggregatorV2V3Interface(address(0)) //sequencer uptime feed AggregatorV2V3Interface 457 | | ); 458 | | 459 | | _setUintDataStoreCall( 460 | | DEPLOYER, 461 | | "MIN_ORACLE_BLOCK_CONFIRMATIONS", 462 | | MIN_ORACLE_BLOCK_CONFIRMATIONS, 463 | | address(0) 464 | | ); 465 | | _setUintDataStoreCall( 466 | | DEPLOYER, 467 | | "MAX_ORACLE_TIMESTAMP_RANGE", 468 | | MAX_ORACLE_TIMESTAMP_RANGE, 469 | | address(0) 470 | | ); 471 | | _setUintDataStoreCall( 472 | | DEPLOYER, 473 | | "MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR", 474 | | MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR, 475 | | address(0) 476 | | ); 477 | | _setAddressDataStoreCall( 478 | | DEPLOYER, 479 | | "CHAINLINK_PAYMENT_TOKEN", 480 | | CHAINLINK_PAYMENT_TOKEN, 481 | | address(0) 482 | | ); 483 | | 484 | | _roleChangingCall(DEPLOYER, address(oracle), Role.CONTROLLER); 485 | | 486 | | chainlinkDataStreamProvider = new ChainlinkDataStreamProvider( 487 | | dataStore, 488 | | address(oracle), 489 | | mockDataStreamVerifier 490 | | ); 491 | | 492 | | _setBoolDataStoreCall( 493 | | DEPLOYER, 494 | | "IS_ORACLE_PROVIDER_ENABLED", 495 | | IS_ORACLE_PROVIDER_ENABLED, 496 | | address(chainlinkDataStreamProvider) 497 | | ); 498 | | 499 | | _setBytes32DataStoreCall( 500 | | DEPLOYER, 501 | | "ORACLE_TYPE", 502 | | address(USDC), 503 | | ORACLE_TYPE_DEFAULT 504 | | ); 505 | | _setAddressDataStoreCall( 506 | | DEPLOYER, 507 | | "ORACLE_PROVIDER_FOR_TOKEN", 508 | | address(gmOracleProvider), 509 | | address(USDC) 510 | | ); //KEY is a string + USDC(added address for a key) 511 | | _setAddressDataStoreCall( 512 | | DEPLOYER, 513 | | "PRICE_FEED", 514 | | address(USDCPriceFeed), 515 | | address(0) 516 | | ); 517 | | _setUintDataStoreCall( 518 | | DEPLOYER, 519 | | "PRICE_FEED_MULTIPLIER", 520 | | PRICE_FEED_MULTIPLIER, 521 | | address(USDC) 522 | | ); 523 | | _setUintDataStoreCall( 524 | | DEPLOYER, 525 | | "PRICE_FEED_HEARTBEAT_DURATION", 526 | | PRICE_FEED_HEARTBEAT_DURATION, 527 | | address(USDC) 528 | | ); 529 | | 530 | | _setBytes32DataStoreCall( 531 | | DEPLOYER, 532 | | "ORACLE_TYPE", 533 | | address(USDT), 534 | | ORACLE_TYPE_DEFAULT 535 | | ); 536 | | _setAddressDataStoreCall( 537 | | DEPLOYER, 538 | | "ORACLE_PROVIDER_FOR_TOKEN", 539 | | address(gmOracleProvider), 540 | | address(USDT) 541 | | ); 542 | | _setAddressDataStoreCall( 543 | | DEPLOYER, 544 | | "PRICE_FEED", 545 | | address(USDTPriceFeed), 546 | | address(0) 547 | | ); 548 | | _setUintDataStoreCall( 549 | | DEPLOYER, 550 | | "PRICE_FEED_MULTIPLIER", 551 | | PRICE_FEED_MULTIPLIER, 552 | | address(USDT) 553 | | ); 554 | | _setUintDataStoreCall( 555 | | DEPLOYER, 556 | | "PRICE_FEED_HEARTBEAT_DURATION", 557 | | PRICE_FEED_HEARTBEAT_DURATION, 558 | | address(USDT) 559 | | ); 560 | | 561 | | _setBytes32DataStoreCall( 562 | | DEPLOYER, 563 | | "ORACLE_TYPE", 564 | | address(WETH), 565 | | ORACLE_TYPE_DEFAULT 566 | | ); 567 | | _setAddressDataStoreCall( 568 | | DEPLOYER, 569 | | "ORACLE_PROVIDER_FOR_TOKEN", 570 | | address(gmOracleProvider), 571 | | address(WETH) 572 | | ); 573 | | 574 | | _setBytes32DataStoreCall( 575 | | DEPLOYER, 576 | | "ORACLE_TYPE", 577 | | address(WBTC), 578 | | ORACLE_TYPE_DEFAULT 579 | | ); 580 | | _setAddressDataStoreCall( 581 | | DEPLOYER, 582 | | "ORACLE_PROVIDER_FOR_TOKEN", 583 | | address(gmOracleProvider), 584 | | address(WBTC) 585 | | ); 586 | | 587 | | _setBytes32DataStoreCall( 588 | | DEPLOYER, 589 | | "ORACLE_TYPE", 590 | | address(SOL), 591 | | ORACLE_TYPE_DEFAULT 592 | | ); //synthetic address 593 | | _setAddressDataStoreCall( 594 | | DEPLOYER, 595 | | "ORACLE_PROVIDER_FOR_TOKEN", 596 | | address(gmOracleProvider), 597 | | address(SOL) 598 | | ); 599 | | 600 | | /** 601 | | * 0_0 * 602 | | * --- Adding custom ChainLink mock--- 603 | | */ 604 | | _setBytes32DataStoreCall( 605 | | DEPLOYER, 606 | | "ORACLE_TYPE", 607 | | address(USDT), 608 | | ORACLE_TYPE_DEFAULT 609 | | ); 610 | | _setAddressDataStoreCall( 611 | | DEPLOYER, 612 | | "ORACLE_PROVIDER_FOR_TOKEN", 613 | | address(chainlinkMock), 614 | | address(USDT) 615 | | ); 616 | | 617 | | _setBytes32DataStoreCall( 618 | | DEPLOYER, 619 | | "ORACLE_TYPE", 620 | | address(USDC), 621 | | ORACLE_TYPE_DEFAULT 622 | | ); 623 | | _setAddressDataStoreCall( 624 | | DEPLOYER, 625 | | "ORACLE_PROVIDER_FOR_TOKEN", 626 | | address(chainlinkMock), 627 | | address(USDC) 628 | | ); 629 | | _setBytes32DataStoreCall( 630 | | DEPLOYER, 631 | | "ORACLE_TYPE", 632 | | address(WETH), 633 | | ORACLE_TYPE_DEFAULT 634 | | ); 635 | | _setAddressDataStoreCall( 636 | | DEPLOYER, 637 | | "ORACLE_PROVIDER_FOR_TOKEN", 638 | | address(chainlinkMock), 639 | | address(WETH) 640 | | ); 641 | | 642 | | _setBytes32DataStoreCall( 643 | | DEPLOYER, 644 | | "ORACLE_TYPE", 645 | | address(WBTC), 646 | | ORACLE_TYPE_DEFAULT 647 | | ); 648 | | _setAddressDataStoreCall( 649 | | DEPLOYER, 650 | | "ORACLE_PROVIDER_FOR_TOKEN", 651 | | address(chainlinkMock), 652 | | address(WBTC) 653 | | ); 654 | | 655 | | _setBytes32DataStoreCall( 656 | | DEPLOYER, 657 | | "ORACLE_TYPE", 658 | | address(SOL), 659 | | ORACLE_TYPE_DEFAULT 660 | | ); //synthetic address 661 | | _setAddressDataStoreCall( 662 | | DEPLOYER, 663 | | "ORACLE_PROVIDER_FOR_TOKEN", 664 | | address(chainlinkMock), 665 | | address(SOL) 666 | | ); 667 | | 668 | | /** 669 | | * 0_0 * 670 | | * --- Deploy order related contracts --- 671 | | */ 672 | | orderVault = new OrderVault(roleStore, dataStore); 673 | | swapHandler = new SwapHandler(roleStore); 674 | | _roleChangingCall(DEPLOYER, address(swapHandler), Role.CONTROLLER); 675 | | 676 | | referralStorage = new ReferralStorage(); 677 | | referralStorage.setTier(0, 1000, 5000); 678 | | referralStorage.setTier(1, 2000, 5000); 679 | | referralStorage.setTier(0, 2500, 4000); 680 | | 681 | | adlHandler = new AdlHandler( 682 | | roleStore, 683 | | dataStore, 684 | | eventEmitter, 685 | | oracle, 686 | | orderVault, 687 | | swapHandler, 688 | | referralStorage 689 | | ); 690 | | _roleChangingCall(DEPLOYER, address(adlHandler), Role.CONTROLLER); 691 | | 692 | | marketFactory = new MarketFactory(roleStore, dataStore, eventEmitter); 693 | | _roleChangingCall(DEPLOYER, address(marketFactory), Role.CONTROLLER); 694 | | 695 | | config = new Config(roleStore, dataStore, eventEmitter); 696 | | _roleChangingCall(DEPLOYER, address(config), Role.CONTROLLER); 697 | | 698 | | /** 699 | | * 0_0 * 700 | | * --- Deploy deposit related contracts --- 701 | | */ 702 | | depositVault = new DepositVault(roleStore, dataStore); 703 | | depositHandler = new DepositHandler( 704 | | roleStore, 705 | | dataStore, 706 | | eventEmitter, 707 | | oracle, 708 | | depositVault 709 | | ); 710 | | _roleChangingCall(DEPLOYER, address(depositHandler), Role.CONTROLLER); 711 | | 712 | | router = new Router(roleStore); 713 | | 714 | | /** 715 | | * 0_0 * 716 | | * --- Deploy withdrawal related contracts --- 717 | | */ 718 | | withdrawalVault = new WithdrawalVault(roleStore, dataStore); 719 | | withdrawalHandler = new WithdrawalHandler( 720 | | roleStore, 721 | | dataStore, 722 | | eventEmitter, 723 | | oracle, 724 | | withdrawalVault 725 | | ); 726 | | _roleChangingCall( 727 | | DEPLOYER, 728 | | address(withdrawalHandler), 729 | | Role.CONTROLLER 730 | | ); 731 | | 732 | | /** 733 | | * 0_0 * 734 | | * --- Deploy shift related contracts --- 735 | | */ 736 | | shiftVault = new ShiftVault(roleStore, dataStore); 737 | | shiftHandler = new ShiftHandler( 738 | | roleStore, 739 | | dataStore, 740 | | eventEmitter, 741 | | oracle, 742 | | shiftVault 743 | | ); 744 | | _roleChangingCall(DEPLOYER, address(shiftHandler), Role.CONTROLLER); 745 | | 746 | | orderHandler = new OrderHandler( 747 | | roleStore, 748 | | dataStore, 749 | | eventEmitter, 750 | | oracle, 751 | | orderVault, 752 | | swapHandler, 753 | | referralStorage 754 | | ); 755 | | 756 | | referralStorage.setHandler(address(orderHandler), true); 757 | | 758 | | _roleChangingCall(DEPLOYER, address(orderHandler), Role.CONTROLLER); 759 | | 760 | | externalHandler = new ExternalHandler(); 761 | | 762 | | exchangeRouter = new ExchangeRouter( 763 | | router, 764 | | roleStore, 765 | | dataStore, 766 | | eventEmitter, 767 | | depositHandler, 768 | | withdrawalHandler, 769 | | shiftHandler, 770 | | orderHandler, 771 | | externalHandler 772 | | ); 773 | | 774 | | _roleChangingCall(DEPLOYER, address(exchangeRouter), Role.CONTROLLER); 775 | | _roleChangingCall( 776 | | DEPLOYER, 777 | | address(exchangeRouter), 778 | | Role.ROUTER_PLUGIN 779 | | ); 780 | | 781 | | feeHandler = new FeeHandler(roleStore, dataStore, eventEmitter); 782 | | _roleChangingCall(DEPLOYER, address(feeHandler), Role.CONTROLLER); 783 | | 784 | | liquidationHandler = new LiquidationHandler( 785 | | roleStore, 786 | | dataStore, 787 | | eventEmitter, 788 | | oracle, 789 | | orderVault, 790 | | swapHandler, 791 | | referralStorage 792 | | ); 793 | | _roleChangingCall( 794 | | DEPLOYER, 795 | | address(liquidationHandler), 796 | | Role.CONTROLLER 797 | | ); 798 | | 799 | | //Simple price feed 800 | | mockPriceFeed = new MockPriceFeed(); 801 | | multicall3 = new Multicall3(); 802 | | 803 | | /** 804 | | * 0_0 * 805 | | * --- Deploy reader related contracts --- 806 | | */ 807 | | subaccountRouter = new SubaccountRouter( 808 | | router, 809 | | roleStore, 810 | | dataStore, 811 | | eventEmitter, 812 | | orderHandler, 813 | | orderVault 814 | | ); 815 | | _roleChangingCall(DEPLOYER, address(subaccountRouter), Role.CONTROLLER); 816 | | _roleChangingCall( 817 | | DEPLOYER, 818 | | address(subaccountRouter), 819 | | Role.ROUTER_PLUGIN 820 | | ); 821 | | 822 | | timelock = new Timelock( 823 | | roleStore, 824 | | dataStore, 825 | | eventEmitter, 826 | | oracleStore, 827 | | 24 * 60 * 60 //timelockDelay 828 | | ); 829 | | _roleChangingCall(DEPLOYER, address(timelock), Role.CONTROLLER); 830 | | _roleChangingCall(DEPLOYER, address(timelock), Role.ROLE_ADMIN); 831 | | 832 | | timestampInitializer = new TimestampInitializer( 833 | | roleStore, 834 | | dataStore, 835 | | eventEmitter 836 | | ); 837 | | _roleChangingCall( 838 | | DEPLOYER, 839 | | address(timestampInitializer), 840 | | Role.CONTROLLER 841 | | ); 842 | | 843 | | reader = new Reader(); 844 | | } 845 | | 846 | | function marketsSetup() internal { 847 | | /** 848 | | * 0_0 * 849 | | * --- New markets, should include all supported combinations --- 850 | | */ 851 | | market_WETH_WETH_USDC = marketFactory 852 | | .createMarket( 853 | | address(WETH), 854 | | address(WETH), 855 | | address(USDC), 856 | | DEFAULT_MARKET_TYPE 857 | | ) 858 | | .marketToken; 859 | | // vm.label(address(market_WETH_WETH_USDC), "market_WETH_WETH_USDC"); 860 | | 861 | | market_WETH_WETH_USDT = marketFactory 862 | | .createMarket( 863 | | address(WETH), 864 | | address(WETH), 865 | | address(USDT), 866 | | DEFAULT_MARKET_TYPE 867 | | ) 868 | | .marketToken; 869 | | // vm.label(address(market_WETH_WETH_USDT), "market_WETH_WETH_USDT"); 870 | | 871 | | market_0_WETH_USDC = marketFactory 872 | | .createMarket( 873 | | address(0), 874 | | address(WETH), 875 | | address(USDC), 876 | | DEFAULT_MARKET_TYPE 877 | | ) 878 | | .marketToken; 879 | | // vm.label(address(market_0_WETH_USDC), "market_0_WETH_USDC"); 880 | | 881 | | market_WBTC_WBTC_USDC = marketFactory 882 | | .createMarket( 883 | | address(WBTC), 884 | | address(WBTC), 885 | | address(USDC), 886 | | DEFAULT_MARKET_TYPE 887 | | ) 888 | | .marketToken; 889 | | // vm.label(address(market_WBTC_WBTC_USDC), "market_WBTC_WBTC_USDC"); 890 | | 891 | | /** 892 | | * 0_0 * 893 | | * --- Config for market_WETH_WETH_USDC --- 894 | | */ 895 | | _setUintDataStoreCall( 896 | | DEPLOYER, 897 | | "MAX_POOL_AMOUNT", 898 | | MAX_POOL_AMOUNT_WETH, 899 | | market_WETH_WETH_USDC, 900 | | address(WETH) 901 | | ); 902 | | _setUintDataStoreCall( 903 | | DEPLOYER, 904 | | "MAX_POOL_AMOUNT", 905 | | MAX_POOL_AMOUNT_USDC, 906 | | market_WETH_WETH_USDC, 907 | | address(USDC) 908 | | ); 909 | | _setUintDataStoreCall( 910 | | DEPLOYER, 911 | | "MAX_POOL_USD_FOR_DEPOSIT", 912 | | MAX_POOL_USD_FOR_DEPOSIT_WETH, 913 | | market_WETH_WETH_USDC, 914 | | address(WETH) 915 | | ); 916 | | _setUintDataStoreCall( 917 | | DEPLOYER, 918 | | "MAX_POOL_USD_FOR_DEPOSIT", 919 | | MAX_POOL_USD_FOR_DEPOSIT_USDC, 920 | | market_WETH_WETH_USDC, 921 | | address(USDC) 922 | | ); 923 | | _setUintDataStoreCall( 924 | | DEPLOYER, 925 | | "MIN_COLLATERAL_FACTOR", 926 | | MIN_COLLATERAL_FACTOR, 927 | | market_WETH_WETH_USDC 928 | | ); 929 | | _setUintDataStoreCall( 930 | | DEPLOYER, 931 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 932 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG, 933 | | market_WETH_WETH_USDC, 934 | | true 935 | | ); 936 | | _setUintDataStoreCall( 937 | | DEPLOYER, 938 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 939 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT, 940 | | market_WETH_WETH_USDC, 941 | | false 942 | | ); 943 | | _setUintDataStoreCall( 944 | | DEPLOYER, 945 | | "MAX_OPEN_INTEREST", 946 | | MAX_OPEN_INTEREST_LONG, 947 | | market_WETH_WETH_USDC, 948 | | true 949 | | ); 950 | | _setUintDataStoreCall( 951 | | DEPLOYER, 952 | | "MAX_OPEN_INTEREST", 953 | | MAX_OPEN_INTEREST_SHORT, 954 | | market_WETH_WETH_USDC, 955 | | false 956 | | ); 957 | | _setUintDataStoreCall( 958 | | DEPLOYER, 959 | | "RESERVE_FACTOR", 960 | | RESERVE_FACTOR_LONG, 961 | | market_WETH_WETH_USDC, 962 | | true 963 | | ); 964 | | _setUintDataStoreCall( 965 | | DEPLOYER, 966 | | "RESERVE_FACTOR", 967 | | RESERVE_FACTOR_SHORT, 968 | | market_WETH_WETH_USDC, 969 | | false 970 | | ); 971 | | _setUintDataStoreCall( 972 | | DEPLOYER, 973 | | "OPEN_INTEREST_RESERVE_FACTOR", 974 | | OPEN_INTEREST_RESERVE_FACTOR_LONG, 975 | | market_WETH_WETH_USDC, 976 | | true 977 | | ); 978 | | _setUintDataStoreCall( 979 | | DEPLOYER, 980 | | "OPEN_INTEREST_RESERVE_FACTOR", 981 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT, 982 | | market_WETH_WETH_USDC, 983 | | false 984 | | ); 985 | | 986 | | _setUintDataStoreCall( 987 | | DEPLOYER, 988 | | "MAX_PNL_FACTOR", 989 | | "MAX_PNL_FACTOR_FOR_TRADERS", 990 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG, 991 | | market_WETH_WETH_USDC, 992 | | true 993 | | ); 994 | | _setUintDataStoreCall( 995 | | DEPLOYER, 996 | | "MAX_PNL_FACTOR", 997 | | "MAX_PNL_FACTOR_FOR_TRADERS", 998 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT, 999 | | market_WETH_WETH_USDC, 1000 | | false 1001 | | ); 1002 | | _setUintDataStoreCall( 1003 | | DEPLOYER, 1004 | | "MAX_PNL_FACTOR", 1005 | | "MAX_PNL_FACTOR_FOR_ADL", 1006 | | MAX_PNL_FACTOR_FOR_ADL_LONG, 1007 | | market_WETH_WETH_USDC, 1008 | | true 1009 | | ); 1010 | | _setUintDataStoreCall( 1011 | | DEPLOYER, 1012 | | "MAX_PNL_FACTOR", 1013 | | "MAX_PNL_FACTOR_FOR_ADL", 1014 | | MAX_PNL_FACTOR_FOR_ADL_SHORT, 1015 | | market_WETH_WETH_USDC, 1016 | | false 1017 | | ); 1018 | | _setUintDataStoreCall( 1019 | | DEPLOYER, 1020 | | "MIN_PNL_FACTOR_AFTER_ADL", 1021 | | MIN_PNL_FACTOR_AFTER_ADL_LONG, 1022 | | market_WETH_WETH_USDC, 1023 | | true 1024 | | ); 1025 | | _setUintDataStoreCall( 1026 | | DEPLOYER, 1027 | | "MIN_PNL_FACTOR_AFTER_ADL", 1028 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT, 1029 | | market_WETH_WETH_USDC, 1030 | | false 1031 | | ); 1032 | | _setUintDataStoreCall( 1033 | | DEPLOYER, 1034 | | "MAX_PNL_FACTOR", 1035 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1036 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG, 1037 | | market_WETH_WETH_USDC, 1038 | | true 1039 | | ); 1040 | | _setUintDataStoreCall( 1041 | | DEPLOYER, 1042 | | "MAX_PNL_FACTOR", 1043 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1044 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT, 1045 | | market_WETH_WETH_USDC, 1046 | | false 1047 | | ); 1048 | | _setUintDataStoreCall( 1049 | | DEPLOYER, 1050 | | "MAX_PNL_FACTOR", 1051 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1052 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG, 1053 | | market_WETH_WETH_USDC, 1054 | | true 1055 | | ); 1056 | | _setUintDataStoreCall( 1057 | | DEPLOYER, 1058 | | "MAX_PNL_FACTOR", 1059 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1060 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT, 1061 | | market_WETH_WETH_USDC, 1062 | | false 1063 | | ); 1064 | | _setUintDataStoreCall( 1065 | | DEPLOYER, 1066 | | "TOKEN_TRANSFER_GAS_LIMIT", 1067 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT, 1068 | | market_WETH_WETH_USDC 1069 | | ); 1070 | | _setUintDataStoreCall( 1071 | | DEPLOYER, 1072 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS", 1073 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS, 1074 | | market_WETH_WETH_USDC 1075 | | ); 1076 | | _setUintDataStoreCall( 1077 | | DEPLOYER, 1078 | | "POSITION_IMPACT_FACTOR", 1079 | | POSITION_IMPACT_FACTOR_POSITIVE, 1080 | | market_WETH_WETH_USDC, 1081 | | true 1082 | | ); 1083 | | _setUintDataStoreCall( 1084 | | DEPLOYER, 1085 | | "POSITION_IMPACT_FACTOR", 1086 | | POSITION_IMPACT_FACTOR_NEGATIVE, 1087 | | market_WETH_WETH_USDC, 1088 | | false 1089 | | ); 1090 | | 1091 | | _setUintDataStoreCall( 1092 | | DEPLOYER, 1093 | | "SWAP_FEE_FACTOR", 1094 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT, 1095 | | market_WETH_WETH_USDC, 1096 | | true 1097 | | ); 1098 | | 1099 | | _setUintDataStoreCall( 1100 | | DEPLOYER, 1101 | | "SWAP_FEE_FACTOR", 1102 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT, 1103 | | market_WETH_WETH_USDC, 1104 | | false 1105 | | ); 1106 | | 1107 | | _setUintDataStoreCall( 1108 | | DEPLOYER, 1109 | | "ATOMIC_SWAP_FEE_FACTOR", 1110 | | ATOMIC_SWAP_FEE_FACTOR, 1111 | | market_WETH_WETH_USDC 1112 | | ); 1113 | | 1114 | | _setUintDataStoreCall( 1115 | | DEPLOYER, 1116 | | "FUNDING_FACTOR", 1117 | | FUNDING_FACTOR, 1118 | | market_WETH_WETH_USDC 1119 | | ); 1120 | | 1121 | | _setUintDataStoreCall( 1122 | | DEPLOYER, 1123 | | "FUNDING_EXPONENT_FACTOR", 1124 | | FUNDING_EXPONENT_FACTOR, 1125 | | market_WETH_WETH_USDC 1126 | | ); 1127 | | 1128 | | _setUintDataStoreCall( 1129 | | DEPLOYER, 1130 | | "THRESHOLD_FOR_STABLE_FUNDING", 1131 | | THRESHOLD_FOR_STABLE_FUNDING, 1132 | | market_WETH_WETH_USDC 1133 | | ); 1134 | | 1135 | | _setUintDataStoreCall( 1136 | | DEPLOYER, 1137 | | "THRESHOLD_FOR_DECREASE_FUNDING", 1138 | | THRESHOLD_FOR_DECREASE_FUNDING, 1139 | | market_WETH_WETH_USDC 1140 | | ); 1141 | | _setUintDataStoreCall( 1142 | | DEPLOYER, 1143 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1144 | | FUNDING_INCREASE_FACTOR_PER_SECOND, 1145 | | market_WETH_WETH_USDC 1146 | | ); 1147 | | _setUintDataStoreCall( 1148 | | DEPLOYER, 1149 | | "FUNDING_DECREASE_FACTOR_PER_SECOND", 1150 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1151 | | market_WETH_WETH_USDC 1152 | | ); 1153 | | _setUintDataStoreCall( 1154 | | DEPLOYER, 1155 | | "MAX_FUNDING_FACTOR_PER_SECOND", 1156 | | MAX_FUNDING_FACTOR_PER_SECOND, 1157 | | market_WETH_WETH_USDC 1158 | | ); 1159 | | _setUintDataStoreCall( 1160 | | DEPLOYER, 1161 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1162 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1163 | | market_WETH_WETH_USDC 1164 | | ); 1165 | | 1166 | | /** 1167 | | * 0_0 * 1168 | | * --- Config for market_WETH_WETH_USDT --- 1169 | | */ 1170 | | _setUintDataStoreCall( 1171 | | DEPLOYER, 1172 | | "MAX_POOL_AMOUNT", 1173 | | MAX_POOL_AMOUNT_WETH, 1174 | | market_WETH_WETH_USDT, 1175 | | address(WETH) 1176 | | ); 1177 | | _setUintDataStoreCall( 1178 | | DEPLOYER, 1179 | | "MAX_POOL_AMOUNT", 1180 | | MAX_POOL_AMOUNT_USDT, 1181 | | market_WETH_WETH_USDT, 1182 | | address(USDT) 1183 | | ); 1184 | | _setUintDataStoreCall( 1185 | | DEPLOYER, 1186 | | "MAX_POOL_USD_FOR_DEPOSIT", 1187 | | MAX_POOL_USD_FOR_DEPOSIT_WETH, 1188 | | market_WETH_WETH_USDT, 1189 | | address(WETH) 1190 | | ); 1191 | | _setUintDataStoreCall( 1192 | | DEPLOYER, 1193 | | "MAX_POOL_USD_FOR_DEPOSIT", 1194 | | MAX_POOL_AMOUNT_USDT, 1195 | | market_WETH_WETH_USDT, 1196 | | address(USDT) 1197 | | ); 1198 | | _setUintDataStoreCall( 1199 | | DEPLOYER, 1200 | | "MIN_COLLATERAL_FACTOR", 1201 | | MIN_COLLATERAL_FACTOR, 1202 | | market_WETH_WETH_USDT 1203 | | ); 1204 | | _setUintDataStoreCall( 1205 | | DEPLOYER, 1206 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 1207 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG, 1208 | | market_WETH_WETH_USDT, 1209 | | true 1210 | | ); 1211 | | _setUintDataStoreCall( 1212 | | DEPLOYER, 1213 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 1214 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT, 1215 | | market_WETH_WETH_USDT, 1216 | | false 1217 | | ); 1218 | | _setUintDataStoreCall( 1219 | | DEPLOYER, 1220 | | "MAX_OPEN_INTEREST", 1221 | | MAX_OPEN_INTEREST_LONG, 1222 | | market_WETH_WETH_USDT, 1223 | | true 1224 | | ); 1225 | | _setUintDataStoreCall( 1226 | | DEPLOYER, 1227 | | "MAX_OPEN_INTEREST", 1228 | | MAX_OPEN_INTEREST_SHORT, 1229 | | market_WETH_WETH_USDT, 1230 | | false 1231 | | ); 1232 | | _setUintDataStoreCall( 1233 | | DEPLOYER, 1234 | | "RESERVE_FACTOR", 1235 | | RESERVE_FACTOR_LONG, 1236 | | market_WETH_WETH_USDT, 1237 | | true 1238 | | ); 1239 | | _setUintDataStoreCall( 1240 | | DEPLOYER, 1241 | | "RESERVE_FACTOR", 1242 | | RESERVE_FACTOR_SHORT, 1243 | | market_WETH_WETH_USDT, 1244 | | false 1245 | | ); 1246 | | _setUintDataStoreCall( 1247 | | DEPLOYER, 1248 | | "OPEN_INTEREST_RESERVE_FACTOR", 1249 | | OPEN_INTEREST_RESERVE_FACTOR_LONG, 1250 | | market_WETH_WETH_USDT, 1251 | | true 1252 | | ); 1253 | | _setUintDataStoreCall( 1254 | | DEPLOYER, 1255 | | "OPEN_INTEREST_RESERVE_FACTOR", 1256 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT, 1257 | | market_WETH_WETH_USDT, 1258 | | false 1259 | | ); 1260 | | 1261 | | _setUintDataStoreCall( 1262 | | DEPLOYER, 1263 | | "MAX_PNL_FACTOR", 1264 | | "MAX_PNL_FACTOR_FOR_TRADERS", 1265 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG, 1266 | | market_WETH_WETH_USDT, 1267 | | true 1268 | | ); 1269 | | _setUintDataStoreCall( 1270 | | DEPLOYER, 1271 | | "MAX_PNL_FACTOR", 1272 | | "MAX_PNL_FACTOR_FOR_TRADERS", 1273 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT, 1274 | | market_WETH_WETH_USDT, 1275 | | false 1276 | | ); 1277 | | _setUintDataStoreCall( 1278 | | DEPLOYER, 1279 | | "MAX_PNL_FACTOR", 1280 | | "MAX_PNL_FACTOR_FOR_ADL", 1281 | | MAX_PNL_FACTOR_FOR_ADL_LONG, 1282 | | market_WETH_WETH_USDT, 1283 | | true 1284 | | ); 1285 | | _setUintDataStoreCall( 1286 | | DEPLOYER, 1287 | | "MAX_PNL_FACTOR", 1288 | | "MAX_PNL_FACTOR_FOR_ADL", 1289 | | MAX_PNL_FACTOR_FOR_ADL_SHORT, 1290 | | market_WETH_WETH_USDT, 1291 | | false 1292 | | ); 1293 | | _setUintDataStoreCall( 1294 | | DEPLOYER, 1295 | | "MIN_PNL_FACTOR_AFTER_ADL", 1296 | | MIN_PNL_FACTOR_AFTER_ADL_LONG, 1297 | | market_WETH_WETH_USDT, 1298 | | true 1299 | | ); 1300 | | _setUintDataStoreCall( 1301 | | DEPLOYER, 1302 | | "MIN_PNL_FACTOR_AFTER_ADL", 1303 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT, 1304 | | market_WETH_WETH_USDT, 1305 | | false 1306 | | ); 1307 | | _setUintDataStoreCall( 1308 | | DEPLOYER, 1309 | | "MAX_PNL_FACTOR", 1310 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1311 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG, 1312 | | market_WETH_WETH_USDT, 1313 | | true 1314 | | ); 1315 | | _setUintDataStoreCall( 1316 | | DEPLOYER, 1317 | | "MAX_PNL_FACTOR", 1318 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1319 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT, 1320 | | market_WETH_WETH_USDT, 1321 | | false 1322 | | ); 1323 | | _setUintDataStoreCall( 1324 | | DEPLOYER, 1325 | | "MAX_PNL_FACTOR", 1326 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1327 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG, 1328 | | market_WETH_WETH_USDT, 1329 | | true 1330 | | ); 1331 | | _setUintDataStoreCall( 1332 | | DEPLOYER, 1333 | | "MAX_PNL_FACTOR", 1334 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1335 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT, 1336 | | market_WETH_WETH_USDT, 1337 | | false 1338 | | ); 1339 | | _setUintDataStoreCall( 1340 | | DEPLOYER, 1341 | | "TOKEN_TRANSFER_GAS_LIMIT", 1342 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT, 1343 | | market_WETH_WETH_USDT 1344 | | ); 1345 | | _setUintDataStoreCall( 1346 | | DEPLOYER, 1347 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS", 1348 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS, 1349 | | market_WETH_WETH_USDT 1350 | | ); 1351 | | _setUintDataStoreCall( 1352 | | DEPLOYER, 1353 | | "POSITION_IMPACT_FACTOR", 1354 | | POSITION_IMPACT_FACTOR_POSITIVE, 1355 | | market_WETH_WETH_USDT, 1356 | | true 1357 | | ); 1358 | | _setUintDataStoreCall( 1359 | | DEPLOYER, 1360 | | "POSITION_IMPACT_FACTOR", 1361 | | POSITION_IMPACT_FACTOR_NEGATIVE, 1362 | | market_WETH_WETH_USDT, 1363 | | false 1364 | | ); 1365 | | 1366 | | _setUintDataStoreCall( 1367 | | DEPLOYER, 1368 | | "SWAP_FEE_FACTOR", 1369 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT, 1370 | | market_WETH_WETH_USDT, 1371 | | true 1372 | | ); 1373 | | 1374 | | _setUintDataStoreCall( 1375 | | DEPLOYER, 1376 | | "SWAP_FEE_FACTOR", 1377 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT, 1378 | | market_WETH_WETH_USDT, 1379 | | false 1380 | | ); 1381 | | 1382 | | _setUintDataStoreCall( 1383 | | DEPLOYER, 1384 | | "ATOMIC_SWAP_FEE_FACTOR", 1385 | | ATOMIC_SWAP_FEE_FACTOR, 1386 | | market_WETH_WETH_USDT 1387 | | ); 1388 | | _setUintDataStoreCall( 1389 | | DEPLOYER, 1390 | | "FUNDING_FACTOR", 1391 | | FUNDING_FACTOR, 1392 | | market_WETH_WETH_USDT 1393 | | ); 1394 | | 1395 | | _setUintDataStoreCall( 1396 | | DEPLOYER, 1397 | | "FUNDING_EXPONENT_FACTOR", 1398 | | FUNDING_EXPONENT_FACTOR, 1399 | | market_WETH_WETH_USDT 1400 | | ); 1401 | | _setUintDataStoreCall( 1402 | | DEPLOYER, 1403 | | "THRESHOLD_FOR_STABLE_FUNDING", 1404 | | THRESHOLD_FOR_STABLE_FUNDING, 1405 | | market_WETH_WETH_USDT 1406 | | ); 1407 | | 1408 | | _setUintDataStoreCall( 1409 | | DEPLOYER, 1410 | | "THRESHOLD_FOR_DECREASE_FUNDING", 1411 | | THRESHOLD_FOR_DECREASE_FUNDING, 1412 | | market_WETH_WETH_USDT 1413 | | ); 1414 | | _setUintDataStoreCall( 1415 | | DEPLOYER, 1416 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1417 | | FUNDING_INCREASE_FACTOR_PER_SECOND, 1418 | | market_WETH_WETH_USDT 1419 | | ); 1420 | | _setUintDataStoreCall( 1421 | | DEPLOYER, 1422 | | "FUNDING_DECREASE_FACTOR_PER_SECOND", 1423 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1424 | | market_WETH_WETH_USDT 1425 | | ); 1426 | | _setUintDataStoreCall( 1427 | | DEPLOYER, 1428 | | "MAX_FUNDING_FACTOR_PER_SECOND", 1429 | | MAX_FUNDING_FACTOR_PER_SECOND, 1430 | | market_WETH_WETH_USDT 1431 | | ); 1432 | | _setUintDataStoreCall( 1433 | | DEPLOYER, 1434 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1435 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1436 | | market_WETH_WETH_USDT 1437 | | ); 1438 | | /** 1439 | | * 0_0 * 1440 | | * --- Config for market_0_WETH_USDC --- 1441 | | */ 1442 | | _setUintDataStoreCall( 1443 | | DEPLOYER, 1444 | | "TOKEN_TRANSFER_GAS_LIMIT", 1445 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT, 1446 | | market_0_WETH_USDC 1447 | | ); 1448 | | _setUintDataStoreCall( 1449 | | DEPLOYER, 1450 | | "MAX_POOL_AMOUNT", 1451 | | MAX_POOL_AMOUNT_WETH, 1452 | | market_0_WETH_USDC, 1453 | | address(WETH) 1454 | | ); 1455 | | _setUintDataStoreCall( 1456 | | DEPLOYER, 1457 | | "MAX_POOL_AMOUNT", 1458 | | MAX_POOL_AMOUNT_USDC, 1459 | | market_0_WETH_USDC, 1460 | | address(USDC) 1461 | | ); 1462 | | _setUintDataStoreCall( 1463 | | DEPLOYER, 1464 | | "MAX_POOL_USD_FOR_DEPOSIT", 1465 | | MAX_POOL_USD_FOR_DEPOSIT_WETH, 1466 | | market_0_WETH_USDC, 1467 | | address(WETH) 1468 | | ); 1469 | | _setUintDataStoreCall( 1470 | | DEPLOYER, 1471 | | "MAX_POOL_USD_FOR_DEPOSIT", 1472 | | MAX_POOL_USD_FOR_DEPOSIT_USDC, 1473 | | market_0_WETH_USDC, 1474 | | address(USDC) 1475 | | ); 1476 | | 1477 | | /** 1478 | | * 0_0 * 1479 | | * --- Config for market_WBTC_WBTC_USDC --- 1480 | | */ 1481 | | _setUintDataStoreCall( 1482 | | DEPLOYER, 1483 | | "MAX_POOL_AMOUNT", 1484 | | MAX_POOL_AMOUNT_WBTC, 1485 | | market_WBTC_WBTC_USDC, 1486 | | address(WBTC) 1487 | | ); 1488 | | _setUintDataStoreCall( 1489 | | DEPLOYER, 1490 | | "MAX_POOL_AMOUNT", 1491 | | MAX_POOL_AMOUNT_USDC, 1492 | | market_WBTC_WBTC_USDC, 1493 | | address(USDC) 1494 | | ); 1495 | | _setUintDataStoreCall( 1496 | | DEPLOYER, 1497 | | "MAX_POOL_USD_FOR_DEPOSIT", 1498 | | MAX_POOL_USD_FOR_DEPOSIT_WBTC, 1499 | | market_WBTC_WBTC_USDC, 1500 | | address(WBTC) 1501 | | ); 1502 | | _setUintDataStoreCall( 1503 | | DEPLOYER, 1504 | | "MAX_POOL_USD_FOR_DEPOSIT", 1505 | | MAX_POOL_USD_FOR_DEPOSIT_USDC, 1506 | | market_WBTC_WBTC_USDC, 1507 | | address(USDC) 1508 | | ); 1509 | | _setUintDataStoreCall( 1510 | | DEPLOYER, 1511 | | "MIN_COLLATERAL_FACTOR", 1512 | | MIN_COLLATERAL_FACTOR, 1513 | | market_WBTC_WBTC_USDC 1514 | | ); 1515 | | _setUintDataStoreCall( 1516 | | DEPLOYER, 1517 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 1518 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_LONG, 1519 | | market_WBTC_WBTC_USDC, 1520 | | true 1521 | | ); 1522 | | _setUintDataStoreCall( 1523 | | DEPLOYER, 1524 | | "MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER", 1525 | | MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER_SHORT, 1526 | | market_WBTC_WBTC_USDC, 1527 | | false 1528 | | ); 1529 | | _setUintDataStoreCall( 1530 | | DEPLOYER, 1531 | | "MAX_OPEN_INTEREST", 1532 | | MAX_OPEN_INTEREST_LONG, 1533 | | market_WBTC_WBTC_USDC, 1534 | | true 1535 | | ); 1536 | | _setUintDataStoreCall( 1537 | | DEPLOYER, 1538 | | "MAX_OPEN_INTEREST", 1539 | | MAX_OPEN_INTEREST_SHORT, 1540 | | market_WBTC_WBTC_USDC, 1541 | | false 1542 | | ); 1543 | | _setUintDataStoreCall( 1544 | | DEPLOYER, 1545 | | "RESERVE_FACTOR", 1546 | | RESERVE_FACTOR_LONG, 1547 | | market_WBTC_WBTC_USDC, 1548 | | true 1549 | | ); 1550 | | _setUintDataStoreCall( 1551 | | DEPLOYER, 1552 | | "RESERVE_FACTOR", 1553 | | RESERVE_FACTOR_SHORT, 1554 | | market_WBTC_WBTC_USDC, 1555 | | false 1556 | | ); 1557 | | _setUintDataStoreCall( 1558 | | DEPLOYER, 1559 | | "OPEN_INTEREST_RESERVE_FACTOR", 1560 | | OPEN_INTEREST_RESERVE_FACTOR_LONG, 1561 | | market_WBTC_WBTC_USDC, 1562 | | true 1563 | | ); 1564 | | _setUintDataStoreCall( 1565 | | DEPLOYER, 1566 | | "OPEN_INTEREST_RESERVE_FACTOR", 1567 | | OPEN_INTEREST_RESERVE_FACTOR_SHORT, 1568 | | market_WBTC_WBTC_USDC, 1569 | | false 1570 | | ); 1571 | | 1572 | | _setUintDataStoreCall( 1573 | | DEPLOYER, 1574 | | "MAX_PNL_FACTOR", 1575 | | "MAX_PNL_FACTOR_FOR_TRADERS", 1576 | | MAX_PNL_FACTOR_FOR_TRADERS_LONG, 1577 | | market_WBTC_WBTC_USDC, 1578 | | true 1579 | | ); 1580 | | _setUintDataStoreCall( 1581 | | DEPLOYER, 1582 | | "MAX_PNL_FACTOR", 1583 | | "MAX_PNL_FACTOR_FOR_TRADERS", 1584 | | MAX_PNL_FACTOR_FOR_TRADERS_SHORT, 1585 | | market_WBTC_WBTC_USDC, 1586 | | false 1587 | | ); 1588 | | _setUintDataStoreCall( 1589 | | DEPLOYER, 1590 | | "MAX_PNL_FACTOR", 1591 | | "MAX_PNL_FACTOR_FOR_ADL", 1592 | | MAX_PNL_FACTOR_FOR_ADL_LONG, 1593 | | market_WBTC_WBTC_USDC, 1594 | | true 1595 | | ); 1596 | | _setUintDataStoreCall( 1597 | | DEPLOYER, 1598 | | "MAX_PNL_FACTOR", 1599 | | "MAX_PNL_FACTOR_FOR_ADL", 1600 | | MAX_PNL_FACTOR_FOR_ADL_SHORT, 1601 | | market_WBTC_WBTC_USDC, 1602 | | false 1603 | | ); 1604 | | _setUintDataStoreCall( 1605 | | DEPLOYER, 1606 | | "MIN_PNL_FACTOR_AFTER_ADL", 1607 | | MIN_PNL_FACTOR_AFTER_ADL_LONG, 1608 | | market_WBTC_WBTC_USDC, 1609 | | true 1610 | | ); 1611 | | _setUintDataStoreCall( 1612 | | DEPLOYER, 1613 | | "MIN_PNL_FACTOR_AFTER_ADL", 1614 | | MIN_PNL_FACTOR_AFTER_ADL_SHORT, 1615 | | market_WBTC_WBTC_USDC, 1616 | | false 1617 | | ); 1618 | | _setUintDataStoreCall( 1619 | | DEPLOYER, 1620 | | "MAX_PNL_FACTOR", 1621 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1622 | | MAX_PNL_FACTOR_FOR_DEPOSITS_LONG, 1623 | | market_WBTC_WBTC_USDC, 1624 | | true 1625 | | ); 1626 | | _setUintDataStoreCall( 1627 | | DEPLOYER, 1628 | | "MAX_PNL_FACTOR", 1629 | | "MAX_PNL_FACTOR_FOR_DEPOSITS", 1630 | | MAX_PNL_FACTOR_FOR_DEPOSITS_SHORT, 1631 | | market_WBTC_WBTC_USDC, 1632 | | false 1633 | | ); 1634 | | _setUintDataStoreCall( 1635 | | DEPLOYER, 1636 | | "MAX_PNL_FACTOR", 1637 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1638 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_LONG, 1639 | | market_WBTC_WBTC_USDC, 1640 | | true 1641 | | ); 1642 | | _setUintDataStoreCall( 1643 | | DEPLOYER, 1644 | | "MAX_PNL_FACTOR", 1645 | | "MAX_PNL_FACTOR_FOR_WITHDRAWALS", 1646 | | MAX_PNL_FACTOR_FOR_WITHDRAWALS_SHORT, 1647 | | market_WBTC_WBTC_USDC, 1648 | | false 1649 | | ); 1650 | | _setUintDataStoreCall( 1651 | | DEPLOYER, 1652 | | "TOKEN_TRANSFER_GAS_LIMIT", 1653 | | MARKET_TOKEN_TRANSFER_GAS_LIMIT, 1654 | | market_WBTC_WBTC_USDC 1655 | | ); 1656 | | _setUintDataStoreCall( 1657 | | DEPLOYER, 1658 | | "MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS", 1659 | | MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS, 1660 | | market_WBTC_WBTC_USDC 1661 | | ); 1662 | | _setUintDataStoreCall( 1663 | | DEPLOYER, 1664 | | "POSITION_IMPACT_FACTOR", 1665 | | POSITION_IMPACT_FACTOR_POSITIVE, 1666 | | market_WBTC_WBTC_USDC, 1667 | | true 1668 | | ); 1669 | | _setUintDataStoreCall( 1670 | | DEPLOYER, 1671 | | "POSITION_IMPACT_FACTOR", 1672 | | POSITION_IMPACT_FACTOR_NEGATIVE, 1673 | | market_WBTC_WBTC_USDC, 1674 | | false 1675 | | ); 1676 | | 1677 | | _setUintDataStoreCall( 1678 | | DEPLOYER, 1679 | | "SWAP_FEE_FACTOR", 1680 | | SWAP_FEE_FACTOR_POSITIVE_IMPACT, 1681 | | market_WBTC_WBTC_USDC, 1682 | | true 1683 | | ); 1684 | | 1685 | | _setUintDataStoreCall( 1686 | | DEPLOYER, 1687 | | "SWAP_FEE_FACTOR", 1688 | | SWAP_FEE_FACTOR_NEGATIVE_IMPACT, 1689 | | market_WBTC_WBTC_USDC, 1690 | | false 1691 | | ); 1692 | | 1693 | | _setUintDataStoreCall( 1694 | | DEPLOYER, 1695 | | "ATOMIC_SWAP_FEE_FACTOR", 1696 | | ATOMIC_SWAP_FEE_FACTOR, 1697 | | market_WBTC_WBTC_USDC 1698 | | ); 1699 | | 1700 | | _setUintDataStoreCall( 1701 | | DEPLOYER, 1702 | | "FUNDING_FACTOR", 1703 | | FUNDING_FACTOR, 1704 | | market_WBTC_WBTC_USDC 1705 | | ); 1706 | | 1707 | | _setUintDataStoreCall( 1708 | | DEPLOYER, 1709 | | "FUNDING_EXPONENT_FACTOR", 1710 | | FUNDING_EXPONENT_FACTOR, 1711 | | market_WBTC_WBTC_USDC 1712 | | ); 1713 | | _setUintDataStoreCall( 1714 | | DEPLOYER, 1715 | | "THRESHOLD_FOR_STABLE_FUNDING", 1716 | | THRESHOLD_FOR_STABLE_FUNDING, 1717 | | market_WBTC_WBTC_USDC 1718 | | ); 1719 | | 1720 | | _setUintDataStoreCall( 1721 | | DEPLOYER, 1722 | | "THRESHOLD_FOR_DECREASE_FUNDING", 1723 | | THRESHOLD_FOR_DECREASE_FUNDING, 1724 | | market_WBTC_WBTC_USDC 1725 | | ); 1726 | | _setUintDataStoreCall( 1727 | | DEPLOYER, 1728 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1729 | | FUNDING_INCREASE_FACTOR_PER_SECOND, 1730 | | market_WBTC_WBTC_USDC 1731 | | ); 1732 | | _setUintDataStoreCall( 1733 | | DEPLOYER, 1734 | | "FUNDING_DECREASE_FACTOR_PER_SECOND", 1735 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1736 | | market_WBTC_WBTC_USDC 1737 | | ); 1738 | | _setUintDataStoreCall( 1739 | | DEPLOYER, 1740 | | "MAX_FUNDING_FACTOR_PER_SECOND", 1741 | | MAX_FUNDING_FACTOR_PER_SECOND, 1742 | | market_WBTC_WBTC_USDC 1743 | | ); 1744 | | _setUintDataStoreCall( 1745 | | DEPLOYER, 1746 | | "FUNDING_INCREASE_FACTOR_PER_SECOND", 1747 | | FUNDING_DECREASE_FACTOR_PER_SECOND, 1748 | | market_WBTC_WBTC_USDC 1749 | | ); 1750 | | 1751 | | //v2.1 remediations 1752 | | _setUintDataStoreCall( 1753 | | DEPLOYER, 1754 | | "MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS", 1755 | | MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS, 1756 | | address(0) 1757 | | ); 1758 | | _setUintDataStoreCall( 1759 | | DEPLOYER, 1760 | | "EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1", 1761 | | EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1, 1762 | | address(0) 1763 | | ); 1764 | | } 1765 | | 1766 | | function userSetup() internal { 1767 | | vm.deal(DEPLOYER, 10000e18); 1768 | | vm.deal(USER0, 10000e18); 1769 | | vm.deal(USER1, 10000e18); 1770 | | vm.deal(USER2, 10000e18); 1771 | | vm.deal(USER3, 10000e18); 1772 | | vm.deal(USER4, 10000e18); 1773 | | vm.deal(USER5, 10000e18); 1774 | | vm.deal(USER6, 10000e18); 1775 | | vm.deal(USER7, 10000e18); 1776 | | vm.deal(USER8, 10000e18); 1777 | | vm.deal(USER9, 10000e18); 1778 | | vm.deal(USER10, 10000e18); 1779 | | vm.deal(USER11, 10000e18); 1780 | | vm.deal(USER12, 10000e18); 1781 | | vm.deal(USER13, 10000e18); 1782 | | vm.deal(paraswapDeployer, 10000e18); 1783 | | } 1784 | | 1785 | | function deployCallbackCotracts() internal { 1786 | | callback = new GasFeeCallbackReceiver(); 1787 | | } 1788 | | 1789 | | function deployGammaVault1x_WETHUSDC() internal { 1790 | | mockData = new MockData(); 1791 | | 1792 | | proxyAdmin = new ProxyAdmin(); 1793 | | 1794 | | gmxUtilsLogic_GammaVault1x_WETHUSDC = new GmxUtils(); 1795 | | bytes memory data = abi.encodeWithSelector( 1796 | | GmxUtils.initialize.selector, 1797 | | address(orderHandler), 1798 | | address(exchangeRouter), 1799 | | address(dataStore), 1800 | | address(orderVault), 1801 | | address(reader), 1802 | | address(referralStorage), 1803 | | address(router) 1804 | | ); 1805 | | 1806 | | gmxUtils_GammaVault1x_WETHUSDC = address( 1807 | | new TransparentUpgradeableProxy( 1808 | | address(gmxUtilsLogic_GammaVault1x_WETHUSDC), 1809 | | address(proxyAdmin), 1810 | | data 1811 | | ) 1812 | | ); 1813 | | payable(gmxUtils_GammaVault1x_WETHUSDC).transfer(10 ether); 1814 | | 1815 | | perpetualVault_GammaVault1x_WETHUSDC = new PerpetualVaultLens(); 1816 | | data = abi.encodeWithSelector( 1817 | | perpetualVault_GammaVault1x_WETHUSDC.initialize.selector, 1818 | | "vault_1x_WETH/USDC", //_name 1819 | | market_WETH_WETH_USDC, //_market 1820 | | gammaKeeper, //_keeper 1821 | | treasury_GammaVault1x_WETHUSDC, //_treasury 1822 | | gmxUtils_GammaVault1x_WETHUSDC, //_gmxUtils 1823 | | 1e8, 1824 | | 1e28 1825 | | ); 1826 | | vault_GammaVault1x_WETHUSDC = payable( 1827 | | new TransparentUpgradeableProxy( 1828 | | address(perpetualVault_GammaVault1x_WETHUSDC), 1829 | | address(proxyAdmin), 1830 | | data 1831 | | ) 1832 | | ); 1833 | | } 1834 | | 1835 | | function deployGammaVault2x_WETHUSDC() internal { 1836 | | proxyAdmin = new ProxyAdmin(); 1837 | | 1838 | | gmxUtilsLogic_GammaVault2x_WETHUSDC = new GmxUtils(); 1839 | | bytes memory data = abi.encodeWithSelector( 1840 | | GmxUtils.initialize.selector, 1841 | | address(orderHandler), 1842 | | address(exchangeRouter), 1843 | | address(dataStore), 1844 | | address(orderVault), 1845 | | address(reader), 1846 | | address(referralStorage), 1847 | | address(router) 1848 | | ); 1849 | | 1850 | | gmxUtils_GammaVault2x_WETHUSDC = address( 1851 | | new TransparentUpgradeableProxy( 1852 | | address(gmxUtilsLogic_GammaVault2x_WETHUSDC), 1853 | | address(proxyAdmin), 1854 | | data 1855 | | ) 1856 | | ); 1857 | | payable(gmxUtils_GammaVault2x_WETHUSDC).transfer(10 ether); 1858 | | 1859 | | perpetualVault_GammaVault2x_WETHUSDC = new PerpetualVaultLens(); 1860 | | data = abi.encodeWithSelector( 1861 | | perpetualVault_GammaVault2x_WETHUSDC.initialize.selector, 1862 | | "vault_2x_WETH/USDC", //_name 1863 | | market_WETH_WETH_USDC, //_market 1864 | | gammaKeeper, //_keeper 1865 | | treasury_GammaVault2x_WETHUSDC, //_treasury 1866 | | gmxUtils_GammaVault2x_WETHUSDC, //_gmxUtils 1867 | | 1e8, 1868 | | 1e28 1869 | | ); 1870 | | vault_GammaVault2x_WETHUSDC = payable( 1871 | | new TransparentUpgradeableProxy( 1872 | | address(perpetualVault_GammaVault2x_WETHUSDC), 1873 | | address(proxyAdmin), 1874 | | data 1875 | | ) 1876 | | ); 1877 | | } 1878 | | 1879 | | function deployGammaVault3x_WETHUSDC() internal { 1880 | | gmxUtilsLogic_GammaVault3x_WETHUSDC = new GmxUtils(); 1881 | | bytes memory data = abi.encodeWithSelector( 1882 | | GmxUtils.initialize.selector, 1883 | | address(orderHandler), 1884 | | address(exchangeRouter), 1885 | | address(dataStore), 1886 | | address(orderVault), 1887 | | address(reader), 1888 | | address(referralStorage), 1889 | | address(router) 1890 | | ); 1891 | | 1892 | | gmxUtils_GammaVault3x_WETHUSDC = address( 1893 | | new TransparentUpgradeableProxy( 1894 | | address(gmxUtilsLogic_GammaVault3x_WETHUSDC), 1895 | | address(proxyAdmin), 1896 | | data 1897 | | ) 1898 | | ); 1899 | | payable(gmxUtils_GammaVault3x_WETHUSDC).transfer(10 ether); 1900 | | 1901 | | perpetualVault_GammaVault3x_WETHUSDC = new PerpetualVaultLens(); 1902 | | data = abi.encodeWithSelector( 1903 | | perpetualVault_GammaVault3x_WETHUSDC.initialize.selector, 1904 | | "vault_3x_WETH/USDC", //_name 1905 | | market_WETH_WETH_USDC, //_market 1906 | | gammaKeeper, //_keeper 1907 | | treasury_GammaVault3x_WETHUSDC, //_treasury 1908 | | gmxUtils_GammaVault3x_WETHUSDC, //_gmxUtils 1909 | | 1e8, 1910 | | 1e28 1911 | | ); 1912 | | vault_GammaVault3x_WETHUSDC = payable( 1913 | | new TransparentUpgradeableProxy( 1914 | | address(perpetualVault_GammaVault3x_WETHUSDC), 1915 | | address(proxyAdmin), 1916 | | data 1917 | | ) 1918 | | ); 1919 | | } 1920 | | 1921 | | function deployGammaVault1x_WBTCUSDC() internal { 1922 | | gmxUtilsLogic_GammaVault1x_WBTCUSDC = new GmxUtils(); 1923 | | bytes memory data = abi.encodeWithSelector( 1924 | | GmxUtils.initialize.selector, 1925 | | address(orderHandler), 1926 | | address(exchangeRouter), 1927 | | address(dataStore), 1928 | | address(orderVault), 1929 | | address(reader), 1930 | | address(referralStorage), 1931 | | address(router) 1932 | | ); 1933 | | 1934 | | gmxUtils_GammaVault1x_WBTCUSDC = address( 1935 | | new TransparentUpgradeableProxy( 1936 | | address(gmxUtilsLogic_GammaVault1x_WBTCUSDC), 1937 | | address(proxyAdmin), 1938 | | data 1939 | | ) 1940 | | ); 1941 | | payable(gmxUtils_GammaVault1x_WBTCUSDC).transfer(10 ether); 1942 | | 1943 | | perpetualVault_GammaVaul1x_WBTCUSDC = new PerpetualVaultLens(); 1944 | | data = abi.encodeWithSelector( 1945 | | perpetualVault_GammaVaul1x_WBTCUSDC.initialize.selector, 1946 | | "vault_1x_WBTC/USDC", //_name 1947 | | market_WBTC_WBTC_USDC, //_market 1948 | | gammaKeeper, //_keeper 1949 | | treasury_GammaVault1x_WBTCUSDC, //_treasury 1950 | | gmxUtils_GammaVault1x_WBTCUSDC, //_gmxUtils 1951 | | 1e8, 1952 | | 1e28 1953 | | ); 1954 | | vault_GammaVault1x_WBTCUSDC = payable( 1955 | | new TransparentUpgradeableProxy( 1956 | | address(perpetualVault_GammaVaul1x_WBTCUSDC), 1957 | | address(proxyAdmin), 1958 | | data 1959 | | ) 1960 | | ); 1961 | | } 1962 | | 1963 | | function deployGammaVault2x_WBTCUSDC() internal { 1964 | | gmxUtilsLogic_GammaVault2x_WBTCUSDC = new GmxUtils(); 1965 | | bytes memory data = abi.encodeWithSelector( 1966 | | GmxUtils.initialize.selector, 1967 | | address(orderHandler), 1968 | | address(exchangeRouter), 1969 | | address(dataStore), 1970 | | address(orderVault), 1971 | | address(reader), 1972 | | address(referralStorage), 1973 | | address(router) 1974 | | ); 1975 | | 1976 | | gmxUtils_GammaVault2x_WBTCUSDC = address( 1977 | | new TransparentUpgradeableProxy( 1978 | | address(gmxUtilsLogic_GammaVault2x_WBTCUSDC), 1979 | | address(proxyAdmin), 1980 | | data 1981 | | ) 1982 | | ); 1983 | | payable(gmxUtils_GammaVault2x_WBTCUSDC).transfer(10 ether); 1984 | | 1985 | | perpetualVault_GammaVault2x_WBTCUSDC = new PerpetualVaultLens(); 1986 | | data = abi.encodeWithSelector( 1987 | | perpetualVault_GammaVault2x_WBTCUSDC.initialize.selector, 1988 | | "vault_2x_WBTC/USDC", //_name 1989 | | market_WBTC_WBTC_USDC, //_market 1990 | | gammaKeeper, //_keeper 1991 | | treasury_GammaVault2x_WBTCUSDC, //_treasury 1992 | | gmxUtils_GammaVault2x_WBTCUSDC, //_gmxUtils 1993 | | 1e8, 1994 | | 1e28 1995 | | ); 1996 | | vault_GammaVault2x_WBTCUSDC = payable( 1997 | | new TransparentUpgradeableProxy( 1998 | | address(perpetualVault_GammaVault2x_WBTCUSDC), 1999 | | address(proxyAdmin), 2000 | | data 2001 | | ) 2002 | | ); 2003 | | } 2004 | | 2005 | | function deployGammaVault3x_WBTCUSDC() internal { 2006 | | gmxUtilsLogic_GammaVault3x_WBTCUSDC = new GmxUtils(); 2007 | | bytes memory data = abi.encodeWithSelector( 2008 | | GmxUtils.initialize.selector, 2009 | | address(orderHandler), 2010 | | address(exchangeRouter), 2011 | | address(dataStore), 2012 | | address(orderVault), 2013 | | address(reader), 2014 | | address(referralStorage), 2015 | | address(router) 2016 | | ); 2017 | | 2018 | | gmxUtils_GammaVault3x_WBTCUSDC = address( 2019 | | new TransparentUpgradeableProxy( 2020 | | address(gmxUtilsLogic_GammaVault3x_WBTCUSDC), 2021 | | address(proxyAdmin), 2022 | | data 2023 | | ) 2024 | | ); 2025 | | payable(gmxUtils_GammaVault3x_WBTCUSDC).transfer(10 ether); 2026 | | 2027 | | perpetualVault_GammaVault3x_WBTCUSDC = new PerpetualVaultLens(); 2028 | | data = abi.encodeWithSelector( 2029 | | perpetualVault_GammaVault3x_WBTCUSDC.initialize.selector, 2030 | | "vault_3x_WBTC/USDC", //_name 2031 | | market_WBTC_WBTC_USDC, //_market 2032 | | gammaKeeper, //_keeper 2033 | | treasury_GammaVault3x_WBTCUSDC, //_treasury 2034 | | gmxUtils_GammaVault3x_WBTCUSDC, //_gmxUtils 2035 | | 1e8, 2036 | | 1e28 2037 | | ); 2038 | | vault_GammaVault3x_WBTCUSDC = payable( 2039 | | new TransparentUpgradeableProxy( 2040 | | address(perpetualVault_GammaVault3x_WBTCUSDC), 2041 | | address(proxyAdmin), 2042 | | data 2043 | | ) 2044 | | ); 2045 | | } 2046 | | 2047 | | function deployDex() internal { 2048 | | // vm.prank(paraswapDeployer); //NOTE: this prank doesnt work in setup, deploying with hevm address 2049 | | vm.prank(HEVM_INITIAL_ADDRESS); //for a foundry compatibility 2050 | | mockDex = new MockDex(); 2051 | | if (msg.sender == HEVM_INITIAL_ADDRESS) { 2052 | | //echidna 2053 | | fl.t( 2054 | | address(mockDex) == 2055 | | address(0x78c362A5690447EA2BBC3E8008502efD13936F79), 2056 | | "Address of DEX should be Paraswap V5 Augustus Swapper" 2057 | | ); 2058 | | } else if (msg.sender == FOUNDRY_DEFAULT_ADDRESS) { 2059 | | fl.t( 2060 | | address(mockDex) == 2061 | | address(0x731a10897d267e19B34503aD902d0A29173Ba4B1), 2062 | | "Address of DEX should be Paraswap V5 Augustus Swapper" 2063 | | ); 2064 | | } 2065 | | 2066 | | // fl.t( 2067 | | // address(mockDex) == 2068 | | // address(0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57), 2069 | | // "Address of DEX should be Paraswap V5 Augustus Swapper" 2070 | | // ); //nonce = 1, nonce = 0 was minting WETH in GMXSetup 2071 | | } 2072 | | 2073 | * | function addLiquidityDex() public { 2074 | * | uint amountWETH = WETH.balanceOf(paraswapDeployer) / 2; 2075 | * | uint amountUSDC = USDC.balanceOf(paraswapDeployer) / 5; 2076 | * | uint amountWBTC = WBTC.balanceOf(paraswapDeployer) / 2; 2077 | | 2078 | *r | mockDex.createPair( 2079 | * | address(WETH), 2080 | * | address(USDC), 2081 | * | 3, //feePercentage 2082 | * | 100, //maxSwapPercentage 2083 | | "WETH/USDC Pair", 2084 | | "WETHUSDC" 2085 | | ); 2086 | | vm.prank(paraswapDeployer); 2087 | | WETH.approve(address(mockDex), type(uint256).max); 2088 | | vm.prank(paraswapDeployer); 2089 | | USDC.approve(address(mockDex), type(uint256).max); 2090 | | vm.prank(paraswapDeployer); 2091 | | mockDex.addLiquidity( 2092 | | address(WETH), 2093 | | address(USDC), 2094 | | amountWETH, 2095 | | amountUSDC, 2096 | | 0, 2097 | | 0 2098 | | ); 2099 | | 2100 | | mockDex.createPair( 2101 | | address(WBTC), 2102 | | address(USDC), 2103 | | 3, //feePercentage 2104 | | 100, //maxSwapPercentage 2105 | | "WBTC/USDC Pair", 2106 | | "WBTCUSDC" 2107 | | ); 2108 | | vm.prank(paraswapDeployer); 2109 | | WBTC.approve(address(mockDex), type(uint256).max); 2110 | | vm.prank(paraswapDeployer); 2111 | | USDC.approve(address(mockDex), type(uint256).max); 2112 | | vm.prank(paraswapDeployer); 2113 | | mockDex.addLiquidity( 2114 | | address(WBTC), 2115 | | address(USDC), 2116 | | amountWBTC, 2117 | | amountUSDC, 2118 | | 0, 2119 | | 0 2120 | | ); 2121 | | } 2122 | | 2123 | | function setVaultsArray() internal { 2124 | | VAULTS = [ 2125 | | vault_GammaVault1x_WETHUSDC, 2126 | | vault_GammaVault2x_WETHUSDC, 2127 | | vault_GammaVault3x_WETHUSDC, 2128 | | vault_GammaVault1x_WBTCUSDC, 2129 | | vault_GammaVault2x_WBTCUSDC, 2130 | | vault_GammaVault3x_WBTCUSDC 2131 | | ]; 2132 | | // vm.label(vault_GammaVault1x_WBTCUSDC, "vault_GammaVault1x_WBTCUSDC"); 2133 | | // vm.label(vault_GammaVault2x_WBTCUSDC, "vault_GammaVault2x_WBTCUSDC"); 2134 | | // vm.label( 2135 | | // gmxUtils_GammaVault3x_WBTCUSDC, 2136 | | // "gmxUtils_GammaVault3x_WBTCUSDC" 2137 | | // ); 2138 | | // vm.label(vault_GammaVault1x_WETHUSDC, "vault_GammaVault1x_WETHUSDC"); 2139 | | // vm.label(vault_GammaVault2x_WETHUSDC, "vault_GammaVault2x_WETHUSDC"); 2140 | | // vm.label(vault_GammaVault3x_WETHUSDC, "vault_GammaVault3x_WETHUSDC"); 2141 | | } 2142 | | 2143 | | function fillVaultMarketMap() internal { 2144 | | // Map WBTC-USDC vaults to their market 2145 | | vaultToMarket[vault_GammaVault1x_WBTCUSDC] = market_WBTC_WBTC_USDC; 2146 | | vaultToMarket[vault_GammaVault2x_WBTCUSDC] = market_WBTC_WBTC_USDC; 2147 | | vaultToMarket[vault_GammaVault3x_WBTCUSDC] = market_WBTC_WBTC_USDC; 2148 | | 2149 | | // Map WETH-USDC vaults to their market 2150 | | vaultToMarket[vault_GammaVault1x_WETHUSDC] = market_WETH_WETH_USDC; 2151 | | vaultToMarket[vault_GammaVault2x_WETHUSDC] = market_WETH_WETH_USDC; 2152 | | vaultToMarket[vault_GammaVault3x_WETHUSDC] = market_WETH_WETH_USDC; 2153 | | } 2154 | | 2155 | | function setRouterInVault() internal { 2156 | | PARASWAP_ROUTER = address(mockDex); 2157 | | 2158 | | PerpetualVaultLens(vault_GammaVault1x_WETHUSDC).setRouter( 2159 | | PARASWAP_ROUTER 2160 | | ); 2161 | | PerpetualVaultLens(vault_GammaVault2x_WETHUSDC).setRouter( 2162 | | PARASWAP_ROUTER 2163 | | ); 2164 | | PerpetualVaultLens(vault_GammaVault3x_WETHUSDC).setRouter( 2165 | | PARASWAP_ROUTER 2166 | | ); 2167 | | PerpetualVaultLens(vault_GammaVault1x_WBTCUSDC).setRouter( 2168 | | PARASWAP_ROUTER 2169 | | ); 2170 | | PerpetualVaultLens(vault_GammaVault2x_WBTCUSDC).setRouter( 2171 | | PARASWAP_ROUTER 2172 | | ); 2173 | | PerpetualVaultLens(vault_GammaVault3x_WBTCUSDC).setRouter( 2174 | | PARASWAP_ROUTER 2175 | | ); 2176 | | } 2177 | | } 2178 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/FuzzStorageVars.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "../utils/FuzzUtils.sol"; 6 | | import "./FuzzGMXConfig.sol"; 7 | | 8 | | /** 9 | | * 0_0 * 10 | | * --- Libraries imports --- 11 | | */ 12 | | 13 | | //ADL 14 | | import "../../contracts/adl/AdlUtils.sol"; 15 | | 16 | | //Gas 17 | | // import "../../contracts/gas/GasUtils.sol"; 18 | | 19 | | //Fee 20 | | import "../../contracts/fee/FeeUtils.sol"; 21 | | import "../../contracts/fee/FeeBatch.sol"; 22 | | 23 | | //Order 24 | | import "../../contracts/order/BaseOrderUtils.sol"; 25 | | import "../../contracts/order/OrderStoreUtils.sol"; 26 | | import "../../contracts/order/OrderEventUtils.sol"; 27 | | import "../../contracts/order/IncreaseOrderUtils.sol"; 28 | | import "../../contracts/order/DecreaseOrderUtils.sol"; 29 | | import "../../contracts/order/SwapOrderUtils.sol"; 30 | | import "../../contracts/order/OrderUtils.sol"; 31 | | 32 | | // Market 33 | | import "../../contracts/market/MarketStoreUtils.sol"; 34 | | import "../../contracts/market/MarketEventUtils.sol"; 35 | | import "../../contracts/market/MarketUtils.sol"; 36 | | 37 | | //Pricing 38 | | import "../../contracts/pricing/SwapPricingUtils.sol"; 39 | | 40 | | //Swap 41 | | import "../../contracts/swap/SwapUtils.sol"; 42 | | 43 | | //Position 44 | | import "../../contracts/position/PositionStoreUtils.sol"; 45 | | import "../../contracts/pricing/PositionPricingUtils.sol"; 46 | | import "../../contracts/position/PositionUtils.sol"; 47 | | import "../../contracts/position/PositionEventUtils.sol"; 48 | | import "../../contracts/position/IncreasePositionUtils.sol"; 49 | | import "../../contracts/position/DecreasePositionSwapUtils.sol"; 50 | | import "../../contracts/position/DecreasePositionCollateralUtils.sol"; 51 | | import "../../contracts/position/DecreasePositionUtils.sol"; 52 | | 53 | | //Referral 54 | | import "../../contracts/referral/ReferralEventUtils.sol"; 55 | | 56 | | //Other libs 57 | | import "../../contracts/token/TokenUtils.sol"; 58 | | import "../../contracts/fee/FeeSwapUtils.sol"; 59 | | import "../../contracts/order/Order.sol"; 60 | | import "../../contracts/order/AutoCancelUtils.sol"; 61 | | import "../../contracts/referral/ReferralTier.sol"; 62 | | import "../../contracts/role/Role.sol"; 63 | | import "../../contracts/deposit/Deposit.sol"; 64 | | import "../../contracts/nonce/NonceUtils.sol"; 65 | | import "../../contracts/fee/FeeBatchStoreUtils.sol"; 66 | | import "../../contracts/test/ArrayTest.sol"; 67 | | import "../../contracts/liquidation/LiquidationUtils.sol"; 68 | | import "../../contracts/position/Position.sol"; 69 | | import "../../contracts/position/DecreasePositionSwapUtils.sol"; 70 | | import "../../contracts/position/PositionUtils.sol"; 71 | | import "../../contracts/position/DecreasePositionUtils.sol"; 72 | | import "../../contracts/position/PositionStoreUtils.sol"; 73 | | import "../../contracts/position/PositionStoreUtils.sol"; 74 | | import "../../contracts/position/DecreasePositionCollateralUtils.sol"; 75 | | import "../../contracts/position/PositionEventUtils.sol"; 76 | | import "../../contracts/position/IncreasePositionUtils.sol"; 77 | | import "../../contracts/withdrawal/WithdrawalStoreUtils.sol"; 78 | | import "../../contracts/withdrawal/ExecuteWithdrawalUtils.sol"; 79 | | import "../../contracts/withdrawal/WithdrawalEventUtils.sol"; 80 | | import "../../contracts/withdrawal/Withdrawal.sol"; 81 | | import "../../contracts/withdrawal/WithdrawalUtils.sol"; 82 | | import "../../contracts/oracle/ChainlinkPriceFeedUtils.sol"; 83 | | import "../../contracts/oracle/OracleUtils.sol"; 84 | | import "../../contracts/oracle/GmOracleUtils.sol"; 85 | | import "../../contracts/utils/Uint256Mask.sol"; 86 | | import "../../contracts/utils/Bits.sol"; 87 | | import "../../contracts/utils/Cast.sol"; 88 | | import "../../contracts/utils/AccountUtils.sol"; 89 | | import "../../contracts/utils/Array.sol"; 90 | | import "../../contracts/utils/Calc.sol"; 91 | | import "../../contracts/utils/Precision.sol"; 92 | | import "../../contracts/utils/Printer.sol"; 93 | | import "../../contracts/utils/EnumerableValues.sol"; 94 | | import "../../contracts/chain/Chain.sol"; 95 | | import "../../contracts/adl/AdlUtils.sol"; 96 | | import "../../contracts/price/Price.sol"; 97 | | import "../../contracts/subaccount/SubaccountUtils.sol"; 98 | | import "../../contracts/market/MarketPoolValueInfo.sol"; 99 | | import "../../contracts/market/MarketUtils.sol"; 100 | | import "../../contracts/market/MarketEventUtils.sol"; 101 | | import "../../contracts/market/MarketStoreUtils.sol"; 102 | | import "../../contracts/market/Market.sol"; 103 | | import "../../contracts/feature/FeatureUtils.sol"; 104 | | import "../../contracts/callback/CallbackUtils.sol"; 105 | | import "../../contracts/data/Keys.sol"; 106 | | import "../../contracts/error/ErrorUtils.sol"; 107 | | import "../../contracts/error/Errors.sol"; 108 | | import "../../contracts/pricing/PositionPricingUtils.sol"; 109 | | import "../../contracts/pricing/PricingUtils.sol"; 110 | | import "../../contracts/pricing/SwapPricingUtils.sol"; 111 | | import "../../contracts/event/EventUtils.sol"; 112 | | 113 | | //Test libs 114 | | import "../../contracts/test/MarketStoreUtilsTest.sol"; 115 | | import "../../contracts/test/GasUsageTest.sol"; 116 | | import "../../contracts/test/WithdrawalStoreUtilsTest.sol"; 117 | | import "../../contracts/test/PricingUtilsTest.sol"; 118 | | import "../../contracts/test/DepositStoreUtilsTest.sol"; 119 | | import "../../contracts/test/OrderStoreUtilsTest.sol"; 120 | | import "../../contracts/test/PositionStoreUtilsTest.sol"; 121 | | 122 | | /** 123 | | * 0_0 * 124 | | * --- Contracts --- 125 | | */ 126 | | 127 | | //Role 128 | | import "../../contracts/role/RoleStore.sol"; 129 | | 130 | | //Data 131 | | import "../../contracts/data/DataStore.sol"; 132 | | 133 | | //Mocks 134 | | import "../../contracts/mock/MintableToken.sol"; 135 | | import "../../contracts/mock/WNT.sol"; 136 | | import "../../contracts/mock/MockPriceFeed.sol"; 137 | | import "../../contracts/mock/MockDataStreamVerifier.sol"; 138 | | import "../../contracts/mock/ReferralStorage.sol"; 139 | | import "../../contracts/mock/Multicall3.sol"; 140 | | import "../mocks/ChainlinkMock.sol"; 141 | | import "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol"; 142 | | 143 | | //Gov 144 | | import "../../contracts/gov/GovTimelockController.sol"; 145 | | import "../../contracts/gov/GovToken.sol"; 146 | | import "../../contracts/gov/ProtocolGovernor.sol"; 147 | | 148 | | //Events 149 | | import "../../contracts/event/EventEmitter.sol"; 150 | | 151 | | // Oracle 152 | | import "../../contracts/oracle/OracleStore.sol"; 153 | | import "../../contracts/oracle/GmOracleProvider.sol"; 154 | | import "../../contracts/oracle/ChainlinkPriceFeedProvider.sol"; 155 | | import "../../contracts/oracle/Oracle.sol"; 156 | | import "../../contracts/oracle/ChainlinkDataStreamProvider.sol"; 157 | | 158 | | //Order 159 | | import "../../contracts/order/OrderVault.sol"; 160 | | 161 | | //Market 162 | | import "../../contracts/market/MarketFactory.sol"; 163 | | 164 | | //Swap 165 | | import "../../contracts/swap/SwapHandler.sol"; 166 | | 167 | | //Exchange 168 | | import "../../contracts/exchange/AdlHandler.sol"; 169 | | import "../../contracts/exchange/DepositHandler.sol"; 170 | | import "../../contracts/exchange/WithdrawalHandler.sol"; 171 | | import "../../contracts/exchange/ShiftHandler.sol"; 172 | | import "../../contracts/exchange/OrderHandler.sol"; 173 | | import "../../contracts/exchange/LiquidationHandler.sol"; 174 | | 175 | | //External 176 | | import "../../contracts/external/ExternalHandler.sol"; 177 | | 178 | | //Callback 179 | | // import "../../contracts/callback/CallbackUtils.sol"; 180 | | 181 | | //Chain 182 | | // import "../../contracts/chain/ChainReader.sol"; 183 | | 184 | | //Config 185 | | import "../../contracts/config/Config.sol"; 186 | | 187 | | //Deposit 188 | | import "../../contracts/deposit/DepositEventUtils.sol"; 189 | | import "../../contracts/deposit/DepositVault.sol"; 190 | | import "../../contracts/deposit/DepositStoreUtils.sol"; 191 | | import "../../contracts/deposit/DepositUtils.sol"; 192 | | // import "../../contracts/deposit/ExecuteDepositUtils.sol"; 193 | | 194 | | //Router 195 | | import "../../contracts/router/Router.sol"; 196 | | import "../../contracts/router/ExchangeRouter.sol"; 197 | | import "../../contracts/router/SubaccountRouter.sol"; 198 | | 199 | | //Withdrawal 200 | | import "../../contracts/withdrawal/WithdrawalVault.sol"; 201 | | import "../../contracts/withdrawal/WithdrawalStoreUtils.sol"; 202 | | import "../../contracts/withdrawal/WithdrawalEventUtils.sol"; 203 | | import "../../contracts/withdrawal/WithdrawalUtils.sol"; 204 | | // import "../../contracts/withdrawal/ExecuteWithdrawalUtils.sol"; 205 | | 206 | | //Shift 207 | | // import "../../contracts/Shift/ShiftVault.sol"; 208 | | // import "../../contracts/Shift/ShiftStoreUtils.sol"; 209 | | // import "../../contracts/Shift/ShiftEventUtils.sol"; 210 | | // import "../../contracts/Shift/ShiftUtils.sol"; 211 | | // import "../../contracts/Shift/Shift.sol"; 212 | | 213 | | //Referral 214 | | import "../../contracts/referral/ReferralUtils.sol"; 215 | | 216 | | //Fee 217 | | import "../../contracts/fee/FeeHandler.sol"; 218 | | 219 | | //Liquidations 220 | | import "../../contracts/liquidation/LiquidationUtils.sol"; 221 | | 222 | | //Reader 223 | | import "../../contracts/reader/ReaderPricingUtils.sol"; 224 | | import "../../contracts/reader/ReaderUtils.sol"; 225 | | import "../../contracts/reader/ReaderDepositUtils.sol"; 226 | | import "../../contracts/reader/ReaderWithdrawalUtils.sol"; 227 | | import "../../contracts/reader/Reader.sol"; 228 | | 229 | | //Timelock 230 | | import "../../contracts/config/Timelock.sol"; 231 | | 232 | | //Migration 233 | | import "../../contracts/migration/TimestampInitializer.sol"; 234 | | 235 | | //Callback contract 236 | | import "./GasFeeCallbackReceiver.sol"; 237 | | 238 | | //Gamma 239 | | 240 | | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 241 | | import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; 242 | | import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; 243 | | import {PerpetualVault} from "../../../../contracts/PerpetualVault.sol"; 244 | | import {MockGmxUtils as GmxUtils} from "../../../mock/MockGMXUtils.sol"; 245 | | import {KeeperProxy} from "../../../../contracts/KeeperProxy.sol"; 246 | | import {MarketPrices, PriceProps} from "../../../../contracts/libraries/StructData.sol"; 247 | | import {MockData} from "../../../mock/MockData.sol"; 248 | | import {PerpetualVaultLens} from "../../../../contracts/PerpetualVaultLens.sol"; 249 | | 250 | | //MOCK DEX 251 | | 252 | | import {MockDex} from "../mocks/MockDEX.sol"; 253 | | 254 | | /** 255 | | * 256 | | * 257 | | * 258 | | * 259 | | */ 260 | | contract FuzzStorageVars is FuzzGMXConfig { 261 | | //Role 262 | | RoleStore internal roleStore; 263 | | 264 | | //Data 265 | | DataStore internal dataStore; 266 | | 267 | | //Mocks 268 | | WNT internal WETH; 269 | | MintableToken internal WBTC; 270 | | MintableToken internal USDC; 271 | | MintableToken internal USDT; 272 | | MockPriceFeed internal USDCPriceFeed; 273 | | MockPriceFeed internal USDTPriceFeed; 274 | | MockPriceFeed internal mockPriceFeed; 275 | | MockDataStreamVerifier internal mockDataStreamVerifier; 276 | | ReferralStorage internal referralStorage; 277 | | Multicall3 internal multicall3; 278 | | AggregatorV2V3Interface internal aggregatorV2V3Interface; //for eventual future deployment, currently address 0 in Oralcle setup 279 | | 280 | | //Gov 281 | | GovTimelockController internal govTimelockController; 282 | | GovToken internal govToken; 283 | | ProtocolGovernor internal protocolGovernor; 284 | | 285 | | //Events 286 | | EventEmitter internal eventEmitter; 287 | | 288 | | //Oracles 289 | | OracleStore internal oracleStore; 290 | | GmOracleProvider internal gmOracleProvider; 291 | | ChainlinkPriceFeedProvider internal chainlinkPriceFeedProvider; 292 | | Oracle internal oracle; 293 | | ChainlinkDataStreamProvider internal chainlinkDataStreamProvider; 294 | | ChainlinkMock internal chainlinkMock; 295 | | 296 | | //Order 297 | | OrderVault internal orderVault; 298 | | 299 | | //Market 300 | | MarketFactory internal marketFactory; 301 | | 302 | | //Swap 303 | | SwapHandler internal swapHandler; 304 | | 305 | | //Exchange 306 | | AdlHandler internal adlHandler; 307 | | DepositHandler internal depositHandler; 308 | | WithdrawalHandler internal withdrawalHandler; 309 | | ShiftHandler internal shiftHandler; 310 | | OrderHandler internal orderHandler; 311 | | LiquidationHandler internal liquidationHandler; 312 | | 313 | | //External 314 | | ExternalHandler internal externalHandler; 315 | | 316 | | //Config 317 | | Config internal config; 318 | | 319 | | //Deposit 320 | | DepositVault internal depositVault; 321 | | 322 | | //Router 323 | | Router internal router; 324 | | ExchangeRouter internal exchangeRouter; 325 | | SubaccountRouter internal subaccountRouter; 326 | | 327 | | //Withdrawal 328 | | WithdrawalVault internal withdrawalVault; 329 | | 330 | | //Shift 331 | | ShiftVault internal shiftVault; 332 | | // ShiftStoreUtils internal shiftStoreUtils; 333 | | // ShiftEventUtils internal shiftEventUtils; 334 | | // ShiftUtils internal shiftUtils; 335 | | 336 | | //Fee 337 | | FeeHandler internal feeHandler; 338 | | 339 | | //Reader 340 | | 341 | | Reader internal reader; 342 | | 343 | | //Timelock 344 | | Timelock internal timelock; 345 | | 346 | | //Migration 347 | | TimestampInitializer internal timestampInitializer; 348 | | 349 | | /** 350 | | * 0_0 * 351 | | * --- MARKETS --- 352 | | */ 353 | | address market_WETH_WETH_USDC; 354 | | address market_WETH_WETH_USDT; 355 | | address market_0_WETH_USDC; 356 | | address market_WBTC_WBTC_USDC; 357 | | 358 | | /** 359 | | * 0_0 * 360 | | * --- CALLBACKS --- 361 | | */ 362 | | 363 | | GasFeeCallbackReceiver internal callback; 364 | | 365 | | /** 366 | | * 0_0 * 367 | | * --- GAMMA --- 368 | | */ 369 | * | mapping(address => address) public vaultToMarket; 370 | | 371 | * | ProxyAdmin public proxyAdmin; 372 | | 373 | * | GmxUtils public gmxUtilsLogic_GammaVault1x_WETHUSDC; 374 | * | GmxUtils public gmxUtilsLogic_GammaVault2x_WETHUSDC; 375 | * | GmxUtils public gmxUtilsLogic_GammaVault3x_WETHUSDC; 376 | | 377 | | // PerpetualVault public perpetualVault_GammaVaul1x_WETHUSDC; 378 | | // PerpetualVault public perpetualVault_GammaVaul2x_WETHUSDC; 379 | | // PerpetualVault public perpetualVault_GammaVault3x_WETHUSDC; //NOTE: using lens 380 | | 381 | * | PerpetualVaultLens public perpetualVault_GammaVault1x_WETHUSDC; 382 | * | PerpetualVaultLens public perpetualVault_GammaVault2x_WETHUSDC; 383 | * | PerpetualVaultLens public perpetualVault_GammaVault3x_WETHUSDC; 384 | | 385 | | address gmxUtils_GammaVault1x_WETHUSDC; 386 | | address gmxUtils_GammaVault2x_WETHUSDC; 387 | | address gmxUtils_GammaVault3x_WETHUSDC; 388 | | address payable vault_GammaVault1x_WETHUSDC; 389 | | address payable vault_GammaVault2x_WETHUSDC; 390 | | address payable vault_GammaVault3x_WETHUSDC; 391 | | 392 | * | GmxUtils public gmxUtilsLogic_GammaVault1x_WBTCUSDC; 393 | * | GmxUtils public gmxUtilsLogic_GammaVault2x_WBTCUSDC; 394 | * | GmxUtils public gmxUtilsLogic_GammaVault3x_WBTCUSDC; 395 | | 396 | * | PerpetualVaultLens public perpetualVault_GammaVaul1x_WBTCUSDC; 397 | * | PerpetualVaultLens public perpetualVault_GammaVault2x_WBTCUSDC; 398 | * | PerpetualVaultLens public perpetualVault_GammaVault3x_WBTCUSDC; 399 | | 400 | | // PerpetualVault public perpetualVault_GammaVaul1x_WBTCUSDC; 401 | | // PerpetualVault public perpetualVault_GammaVault2x_WBTCUSDC; 402 | | // PerpetualVault public perpetualVault_GammaVault3x_WBTCUSDC; 403 | | 404 | | address gmxUtils_GammaVault1x_WBTCUSDC; 405 | | address gmxUtils_GammaVault2x_WBTCUSDC; 406 | | address gmxUtils_GammaVault3x_WBTCUSDC; 407 | | 408 | | address payable vault_GammaVault1x_WBTCUSDC; 409 | | address payable vault_GammaVault2x_WBTCUSDC; 410 | | address payable vault_GammaVault3x_WBTCUSDC; 411 | | 412 | | address[6] internal VAULTS; 413 | | 414 | * | MockData public mockData; 415 | | /** 416 | | * 0_0 * 417 | | * --- DEX Mock --- 418 | | */ 419 | | 420 | * | MockDex public mockDex; 421 | | address PARASWAP_ROUTER; 422 | | 423 | | bool DEBUG = true; 424 | | } 425 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/setup/GasFeeCallbackReceiver.sol 1 | | // SPDX-License-Identifier: BUSL-1.1 2 | | 3 | | pragma solidity ^0.8.0; 4 | | import "fuzzlib/FuzzBase.sol"; 5 | | 6 | | import "../../contracts/event/EventUtils.sol"; 7 | | import "../../contracts/deposit/Deposit.sol"; 8 | | import "../../contracts/withdrawal/Withdrawal.sol"; 9 | | import "../../contracts/shift/Shift.sol"; 10 | | import "../../contracts/order/Order.sol"; 11 | | 12 | * | contract GasFeeCallbackReceiver is FuzzBase { 13 | * | function refundExecutionFee( 14 | | bytes32 key, 15 | | EventUtils.EventLogData memory eventData 16 | | ) public payable {} 17 | | 18 | * | function afterDepositExecution( 19 | | bytes32 key, 20 | | Deposit.Props memory deposit, 21 | | EventUtils.EventLogData memory eventData 22 | | ) public payable {} 23 | | 24 | * | function afterDepositCancellation( 25 | | bytes32 key, 26 | | Deposit.Props memory deposit, 27 | | EventUtils.EventLogData memory eventData 28 | | ) public payable {} 29 | | 30 | | function afterWithdrawalExecution( 31 | | bytes32 key, 32 | | Withdrawal.Props memory withdrawal, 33 | | EventUtils.EventLogData memory eventData 34 | | ) public payable {} 35 | | 36 | | function afterWithdrawalCancellation( 37 | | bytes32 key, 38 | | Withdrawal.Props memory withdrawal, 39 | | EventUtils.EventLogData memory eventData 40 | | ) public payable {} 41 | | 42 | | function afterShiftExecution( 43 | | bytes32 key, 44 | | Shift.Props memory shift, 45 | | EventUtils.EventLogData memory eventData 46 | | ) public payable {} 47 | | 48 | | function afterShiftCancellation( 49 | | bytes32 key, 50 | | Shift.Props memory shift, 51 | | EventUtils.EventLogData memory eventData 52 | | ) public payable {} 53 | | 54 | * | function afterOrderExecution( 55 | | bytes32 key, 56 | | Order.Props memory order, 57 | | EventUtils.EventLogData memory eventData 58 | | ) public payable {} 59 | | 60 | * | function afterOrderCancellation( 61 | | bytes32 key, 62 | | Order.Props memory order, 63 | | EventUtils.EventLogData memory eventData 64 | | ) public payable {} 65 | | 66 | * | function afterOrderFrozen( 67 | | bytes32 key, 68 | | Order.Props memory order, 69 | | EventUtils.EventLogData memory eventData 70 | | ) public payable {} 71 | | 72 | * | function cleanETHBalance(address user) public { 73 | * | address(user).call{value: address(this).balance}(""); 74 | | } 75 | | 76 | | receive() external payable {} 77 | | } 78 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FunctionCalls.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | | import "../setup/FuzzStorageVars.sol"; 5 | | import "fuzzlib/FuzzBase.sol"; 6 | | import {Test, console2} from "forge-std/Test.sol"; 7 | | import {IHevm} from "fuzzlib/IHevm.sol"; 8 | | 9 | | abstract contract FunctionCalls is FuzzStorageVars, FuzzBase, Test { 10 | | // IHevm internal hevm = IHevm(address(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)); //workaround for direct prank call 11 | | 12 | | //Events 13 | | event RoleChangingCall( 14 | | address caller, 15 | | address grantedTo, 16 | | bytes32 role, 17 | | bool success 18 | | ); 19 | | event OracleSignerAdded(address caller, address addedSigner, bool success); 20 | | event SetUintDataStoreCall( 21 | | address caller, 22 | | bytes32 key, 23 | | uint256 value, 24 | | bool success 25 | | ); 26 | | event SetBoolDataStoreCall( 27 | | address caller, 28 | | bytes32 key, 29 | | bool value, 30 | | bool success 31 | | ); 32 | | event SetBytes32DataStoreCall( 33 | | address caller, 34 | | bytes32 key, 35 | | bytes32 value, 36 | | bool success 37 | | ); 38 | | event SetAddressDataStoreCall( 39 | | address caller, 40 | | bytes32 key, 41 | | address addressTo, 42 | | bool success 43 | | ); 44 | | 45 | | error dataWriteError(); 46 | | 47 | | // GAMMA Functions 48 | | 49 | * | function _gamma_DepositCall( 50 | | address user, 51 | | address vault, 52 | | uint256 amount, 53 | | uint256 executionFee 54 | * | ) internal returns (bool success, bytes memory returnData) { 55 | * | bytes memory data = abi.encodeWithSelector( 56 | * | PerpetualVaultLens.deposit.selector, 57 | * | amount 58 | | ); 59 | | 60 | * | uint256 value = executionFee * tx.gasprice; 61 | * | vm.prank(user); 62 | * | (success, returnData) = vault.call{value: value}(data); 63 | | } 64 | | 65 | * | function _gamma_CanceDepositCall( 66 | | address vault, 67 | | address gammaKeeper 68 | * | ) internal returns (bool success, bytes memory returnData) { 69 | * | bytes memory data = abi.encodeWithSelector( 70 | * | PerpetualVault.cancelDeposit.selector 71 | | ); 72 | | 73 | * | vm.prank(gammaKeeper); 74 | * | (success, returnData) = vault.call(data); 75 | | } 76 | | 77 | * | function _gamma_WithdrawCall( 78 | | address user, 79 | | address vault, 80 | | uint256 depositId, 81 | | uint256 executionFee 82 | * | ) internal returns (bool success, bytes memory returnData) { 83 | * | bytes memory data = abi.encodeWithSelector( 84 | * | PerpetualVaultLens.withdraw.selector, 85 | * | user, 86 | * | depositId 87 | | ); 88 | | 89 | * | uint256 value = (executionFee * tx.gasprice) * 2; //NOTE: 2 executions 90 | * | vm.prank(user); 91 | * | (success, returnData) = vault.call{value: value}(data); 92 | | } 93 | | 94 | | // GMX Functions 95 | | function _roleChangingCall( 96 | | address caller, 97 | | address to, 98 | | bytes32 role 99 | | ) internal returns (bool success, bytes memory returnData) { 100 | | vm.prank(caller); 101 | | (success, returnData) = address(roleStore).call{gas: 1000000}( 102 | | abi.encodeWithSelector(RoleStore.grantRole.selector, to, role) 103 | | ); 104 | | if (!success) { 105 | | revert dataWriteError(); 106 | | } 107 | | emit RoleChangingCall(caller, to, role, success); 108 | | } 109 | | 110 | | function _oracleAddSignerCall( 111 | | address controller, 112 | | address to 113 | | ) internal returns (bool success, bytes memory returnData) { 114 | | vm.prank(controller); 115 | | (success, returnData) = address(oracleStore).call{gas: 1000000}( 116 | | abi.encodeWithSelector(OracleStore.addSigner.selector, to) 117 | | ); 118 | | if (!success) { 119 | | revert dataWriteError(); 120 | | } 121 | | emit OracleSignerAdded(controller, to, success); 122 | | } 123 | | 124 | | function _setUintDataStoreCall( 125 | | address caller, 126 | | string memory key, 127 | | uint256 value, 128 | | address addedAddress 129 | | ) internal returns (bool success, bytes memory returnData) { 130 | | bytes32 hashedKey; 131 | | if (addedAddress != address(0)) { 132 | | hashedKey = keccak256( 133 | | abi.encode(keccak256(abi.encode(key)), addedAddress) 134 | | ); 135 | | } else { 136 | | hashedKey = keccak256(abi.encode(key)); 137 | | } 138 | | vm.prank(caller); 139 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 140 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value) 141 | | ); 142 | | if (!success) { 143 | | revert dataWriteError(); 144 | | } 145 | | emit SetUintDataStoreCall(caller, hashedKey, value, success); 146 | | } 147 | | 148 | | function _setUintDataStoreCall( 149 | | address caller, 150 | | string memory key, 151 | | uint256 value, 152 | | address addr1, 153 | | address addr2 154 | | ) internal returns (bool success, bytes memory returnData) { 155 | | bytes32 hashedKey; 156 | | hashedKey = _hashData(key, addr1, addr2); 157 | | 158 | | vm.prank(caller); 159 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 160 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value) 161 | | ); 162 | | if (!success) { 163 | | revert dataWriteError(); 164 | | } 165 | | emit SetUintDataStoreCall(caller, hashedKey, value, success); 166 | | } 167 | | 168 | | function _setUintDataStoreCall( 169 | | address caller, 170 | | string memory key, 171 | | uint256 value, 172 | | address addr1, 173 | | bool addedBool 174 | | ) internal returns (bool success, bytes memory returnData) { 175 | | bytes32 hashedKey; 176 | | hashedKey = _hashData(key, addr1, addedBool); 177 | | 178 | | vm.prank(caller); 179 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 180 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value) 181 | | ); 182 | | if (!success) { 183 | | revert dataWriteError(); 184 | | } 185 | | emit SetUintDataStoreCall(caller, hashedKey, value, success); 186 | | } 187 | | 188 | | function _setUintWithBoolDataStoreCall( 189 | | address caller, 190 | | string memory key, 191 | | uint256 value, 192 | | bool addedBool 193 | | ) internal returns (bool success, bytes memory returnData) { 194 | | bytes32 hashedKey = keccak256( 195 | | abi.encode(keccak256(abi.encode(key)), addedBool) 196 | | ); 197 | | 198 | | vm.prank(caller); 199 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 200 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value) 201 | | ); 202 | | if (!success) { 203 | | revert dataWriteError(); 204 | | } 205 | | emit SetUintDataStoreCall(caller, hashedKey, value, success); 206 | | } 207 | | 208 | | function _setAddressDataStoreCall( 209 | | address caller, 210 | | string memory key, 211 | | address addressAsValue, 212 | | address addedAddress 213 | | ) internal returns (bool success, bytes memory returnData) { 214 | | bytes32 hashedKey; 215 | | if (addedAddress != address(0)) { 216 | | hashedKey = keccak256( 217 | | abi.encode(keccak256(abi.encode(key)), addedAddress) 218 | | ); 219 | | } else { 220 | | hashedKey = keccak256(abi.encode(key)); 221 | | } 222 | | vm.prank(caller); 223 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 224 | | abi.encodeWithSelector( 225 | | DataStore.setAddress.selector, 226 | | hashedKey, 227 | | addressAsValue 228 | | ) 229 | | ); 230 | | if (!success) { 231 | | revert dataWriteError(); 232 | | } 233 | | emit SetAddressDataStoreCall( 234 | | caller, 235 | | hashedKey, 236 | | addressAsValue, 237 | | success 238 | | ); 239 | | } 240 | | 241 | | function _setUintDataStoreCall( 242 | | address caller, 243 | | string memory string1, 244 | | string memory string2, 245 | | uint256 value, 246 | | address market, 247 | | bool isLong 248 | | ) internal returns (bool success, bytes memory returnData) { 249 | | bytes32 hashedString1 = keccak256(abi.encode(string1)); 250 | | 251 | | bytes32 hashedKey = keccak256( 252 | | abi.encode( 253 | | hashedString1, 254 | | keccak256(abi.encode(string2)), 255 | | market, 256 | | isLong 257 | | ) 258 | | ); 259 | | 260 | | vm.prank(caller); 261 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 262 | | abi.encodeWithSelector(DataStore.setUint.selector, hashedKey, value) 263 | | ); 264 | | if (!success) { 265 | | revert dataWriteError(); 266 | | } 267 | | emit SetUintDataStoreCall(caller, hashedKey, value, success); 268 | | } 269 | | 270 | | function _setBoolDataStoreCall( 271 | | address caller, 272 | | string memory key, 273 | | bool value, 274 | | address addedAddress 275 | | ) internal returns (bool success, bytes memory returnData) { 276 | | bytes32 hashedKey; 277 | | if (addedAddress != address(0)) { 278 | | hashedKey = keccak256( 279 | | abi.encode(keccak256(abi.encode(key)), addedAddress) 280 | | ); 281 | | } else { 282 | | hashedKey = keccak256(abi.encode(key)); 283 | | } 284 | | 285 | | vm.prank(caller); 286 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 287 | | abi.encodeWithSelector(DataStore.setBool.selector, hashedKey, value) 288 | | ); 289 | | if (!success) { 290 | | revert dataWriteError(); 291 | | } 292 | | emit SetBoolDataStoreCall(caller, hashedKey, value, success); 293 | | } 294 | | 295 | | function _setBytes32DataStoreCall( 296 | | address caller, 297 | | string memory key, 298 | | address addedAddress, 299 | | bytes32 value 300 | | ) internal returns (bool success, bytes memory returnData) { 301 | | bytes32 hashedKey; 302 | | hashedKey = keccak256( 303 | | abi.encode(keccak256(abi.encode(key)), addedAddress) 304 | | ); 305 | | 306 | | vm.prank(caller); 307 | | (success, returnData) = address(dataStore).call{gas: 1000000}( 308 | | abi.encodeWithSelector( 309 | | DataStore.setBytes32.selector, 310 | | hashedKey, 311 | | value 312 | | ) 313 | | ); 314 | | if (!success) { 315 | | revert dataWriteError(); 316 | | } 317 | | emit SetBytes32DataStoreCall(caller, hashedKey, value, success); 318 | | } 319 | | } 320 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FuzzActors.sol 1 | | // SPDX-License-Identifier: MIT 2 | | 3 | | pragma solidity ^0.8.0; 4 | | 5 | | import "./FunctionCalls.sol"; 6 | | 7 | | contract FuzzActors is FunctionCalls { 8 | | address internal DEPLOYER; 9 | | address internal HEVM_INITIAL_ADDRESS = 10 | | address(0x00a329c0648769A73afAc7F9381E08FB43dBEA72); 11 | | address internal FOUNDRY_INITIAL_ADDRESS = 12 | | address(0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496); 13 | | address internal FOUNDRY_DEFAULT_ADDRESS = 14 | | 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38; 15 | | 16 | | address internal gammaKeeper = address(0xeeefeee); 17 | | 18 | | address payable internal treasury_GammaVault1x_WETHUSDC = 19 | | payable(address(0xea1)); 20 | | address payable internal treasury_GammaVault2x_WETHUSDC = 21 | | payable(address(0xea2)); 22 | | address payable internal treasury_GammaVault3x_WETHUSDC = 23 | | payable(address(0xea3)); 24 | | 25 | | address payable internal treasury_GammaVault1x_WBTCUSDC = 26 | | payable(address(0xea1)); 27 | | address payable internal treasury_GammaVault2x_WBTCUSDC = 28 | | payable(address(0xea2)); 29 | | address payable internal treasury_GammaVault3x_WBTCUSDC = 30 | | payable(address(0xea3)); 31 | | 32 | | address internal paraswapDeployer = 33 | | address(0xf01121e808F782d7F34E857c27dA31AD1f151b39); 34 | | 35 | | address internal USER0 = address(10101); 36 | | address internal USER1 = address(1); 37 | | address internal USER2 = address(2); 38 | | address internal USER3 = address(3); 39 | | address internal USER4 = address(4); 40 | | address internal USER5 = address(5); 41 | | address internal USER6 = address(6); 42 | | address internal USER7 = address(7); 43 | | address internal USER8 = address(8); 44 | | address internal USER9 = address(9); 45 | | address internal USER10 = address(10); 46 | | address internal USER11 = address(11); 47 | | address internal USER12 = address(12); 48 | | address internal USER13 = address(13); 49 | | 50 | | address[] internal USERS = [ 51 | | USER0, 52 | | USER1, 53 | | USER2, 54 | | USER3, 55 | | USER4, 56 | | USER5, 57 | | USER6, 58 | | USER7, 59 | | USER8, 60 | | USER9, 61 | | USER10, 62 | | USER11, 63 | | USER12, 64 | | USER13 65 | | ]; 66 | | } 67 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/fuzzing/echidna/utils/FuzzUtils.sol 1 | | // SPDX-License-Identifier: MIT 2 | | pragma solidity ^0.8.0; 3 | | 4 | * | contract FuzzUtils { 5 | | function _getSyntheticTokenAddress(string memory tokenSymbol) internal view returns (address) { 6 | | uint256 chainId = block.chainid; 7 | | bytes32 hashedData = keccak256(abi.encode(chainId, tokenSymbol)); 8 | | bytes20 addressBytes = bytes20(hashedData << 96); 9 | | return address(addressBytes); 10 | | } 11 | | 12 | | function _hashData( 13 | | string memory key, 14 | | address address1, 15 | | address address2 16 | | ) internal pure returns (bytes32) { 17 | | bytes32 hashedKey = keccak256(abi.encode(keccak256(abi.encode(key)), address1, address2)); 18 | | return hashedKey; 19 | | } 20 | | 21 | | function _hashData( 22 | | string memory key, 23 | | address address1, 24 | | bool addedBool 25 | | ) internal pure returns (bytes32) { 26 | | bytes32 hashedKey = keccak256(abi.encode(keccak256(abi.encode(key)), address1, addedBool)); 27 | | return hashedKey; 28 | | } 29 | | } 30 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/mock/MockData.sol 1 | | // SPDX-License-Identifier: UNLICENSED 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import {Test, console} from "forge-std/Test.sol"; 5 | | import {MarketPrices, PriceProps} from "../../contracts/libraries/StructData.sol"; 6 | | 7 | * | contract MockData { 8 | | struct OracleSetPriceParams { 9 | | address[] tokens; 10 | | address[] providers; 11 | | bytes[] data; 12 | | } 13 | | 14 | | function getMarketPrices() 15 | | external 16 | | pure 17 | | returns (MarketPrices memory marketPrices) 18 | | { 19 | | marketPrices.indexTokenPrice = PriceProps({ 20 | | min: 3419847300000000, 21 | | max: 3419869700000000 22 | | }); 23 | | marketPrices.longTokenPrice = PriceProps({ 24 | | min: 3419847300000000, 25 | | max: 3419869700000000 26 | | }); 27 | | marketPrices.shortTokenPrice = PriceProps({ 28 | | min: 999950180000000000000000, 29 | | max: 1000024800000000000000000 30 | | }); 31 | | } 32 | | 33 | | function getOraclePrices() external pure returns (PriceProps[] memory) { 34 | | PriceProps[] memory prices = new PriceProps[](2); 35 | | prices[0] = PriceProps({min: 3419847300000000, max: 3419869700000000}); 36 | | prices[1] = PriceProps({ 37 | | min: 999950180000000000000000, 38 | | max: 1000024800000000000000000 39 | | }); 40 | | 41 | | return prices; 42 | | } 43 | | 44 | | function getOracleParams() 45 | | external 46 | | pure 47 | | returns (OracleSetPriceParams memory params) 48 | | { 49 | | params.tokens = new address[](2); 50 | | params.tokens[0] = address(0x82aF49447D8a07e3bd95BD0d56f35241523fBab1); 51 | | params.tokens[1] = address(0xaf88d065e77c8cC2239327C5EDb3A432268e5831); 52 | | params.providers = new address[](2); 53 | | params.providers[0] = address( 54 | | 0x83cBb05AA78014305194450c4AADAc887fe5DF7F 55 | | ); 56 | | params.providers[1] = address( 57 | | 0x83cBb05AA78014305194450c4AADAc887fe5DF7F 58 | | ); 59 | | params.data = new bytes[](2); 60 | | params.data[ 61 | | 0 62 | | ] = hex"0006f100c86a0007ed73322d6e26606c9985fd511be9d92cf5af6b3dda8143c7000000000000000000000000000000000000000000000000000000000ae8e50a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030000000100010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000362205e10b3a147d02792eccee483dca6c7b44ecce7012cb8c6e0b68b3ae900000000000000000000000000000000000000000000000000000000669949e600000000000000000000000000000000000000000000000000000000669949e60000000000000000000000000000000000000000000000000000551d78bf0938000000000000000000000000000000000000000000000000005322d2ac29a26c00000000000000000000000000000000000000000000000000000000669a9b660000000000000000000000000000000000000000000000b95cff9c1026ae40000000000000000000000000000000000000000000000000b95c4df953f7e940000000000000000000000000000000000000000000000000b95db199bf65ed80000000000000000000000000000000000000000000000000000000000000000006d18dc8df172f8ff7e170ba49dcb29f43a15f93cdef2b7f1d0ae3b82ab13caac2325d14bb01fff320f57dda003397bdae87eb799ed6a7ba9a627e1977432739e37df4c18b224a5408d7d60d20028188b6569db49a3df91fa6ae6674fccb8768c27f23bad9cdcb616e035c64b1b5cb06bd2d1141d4103cac01f4cf5e15c32a24b4b3cdd3ccfee8a3ea58c715efd1dea13d5bbdae658ba3d69215002dbf1af6d0a108928a08795e3e217919d1545db34859e667b246b608413a97b4863d4678100800000000000000000000000000000000000000000000000000000000000000065cc304c8f052759efe955ff541920728a157dd7cf0a7d8ab609523b8a35d85bd617bd1fa6537d8e7e483354be180502a6dcd3b60a8591dd33112ca643e3eaa5c1723fecccb473f16e6247a38c252968d9565c88dad115c964efc2062525655615eff0d54067a12e235d0967472ceda0486a5167e03334f44fcf0fc8f3a5c0cbe512d6582e44bcff0b3192e379df3bf81ab13c314e687e06dd772151ffac8811646d53f3cea69dcb73b1c727fb662502528bf238580d367fbd34e12c8fcf2d509"; 63 | | params.data[ 64 | | 1 65 | | ] = hex"00064c28ccf99cc505d648ffcbc4c2c613859826fd4552841a6822b51800d961000000000000000000000000000000000000000000000000000000000ac42e17000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000001010000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000038f83323b6b08116d1614cf33a9bd71ab5e0abf0c9f1b783a74a43e7bd99200000000000000000000000000000000000000000000000000000000669949e600000000000000000000000000000000000000000000000000000000669949e60000000000000000000000000000000000000000000000000000551edd373de4000000000000000000000000000000000000000000000000005322d2ac29a26c00000000000000000000000000000000000000000000000000000000669a9b660000000000000000000000000000000000000000000000000de0bf578b8418000000000000000000000000000000000000000000000000000de0af043c246c000000000000000000000000000000000000000000000000000de0cfb67f1f38000000000000000000000000000000000000000000000000000000000000000006176fdcbe9c1717344c64be7e30d543a72ec9960b275b4c064a90432e8408dfc3bd436a7c8d6b1041b935369da8accf79883d6ad5926e26f589b0f4962e2e6e9055ee71b93883799865de7863a1a336864cd6e0399a4129dd743f9ede31fb71c3e0f4b056e12177458c94b5e3dc36e93fd47f1f4deefa16bd8ba1d200217fe7089e2599c205dea1b83f069266d3d8290d598654a4a01f9a307fcac5d94cc826c5e2e7e0470b9606c8ff79cda41a8cfca602e25330f14233e7c2d65bfab64fd50b000000000000000000000000000000000000000000000000000000000000000657989c03317218d871a6e5cc59bec63fa4793b007a20f56adacfac96d55f206f19fb8653cf4de2b7831032f01175b648a24d315197bb00991383395f38d7694126f4dc31b1df1f8139958ba2df47db457d1ac573a59c1223235de884074aa3c7687b072a819066ca90f206af10e95218d04afe9d79fdbdaba50759113bfd142d176774fffe4f0db45768c67e8f08ca2f82b6acfabd5abe5475153f4dbba4140c3350982bc21338060ff64137dfdf231cfa25d35ae829ccaa983adfa2a1f26a67"; 66 | | } 67 | | 68 | | function getParaSwapData( 69 | | address receiver 70 | | ) external pure returns (bytes memory) { 71 | | bytes memory rev = abi.encodePacked(receiver); 72 | | bytes 73 | | memory original = hex"000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5700000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000056446c67b6d0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583100000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000000000000286524c9166933d300000000000000000000000000000000000000000000000028991bf71f8751ac00000000000000000000000005c05fc1acf6a113b2235117a5264252d61383cd00000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000066994b15cfa2c4a6f06f493098741ef2682cf0fd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000369a2fdb910d432f0a07381a5e3d27572c876713000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000066a2845e0000000000000000000000000000000000000000000000000000000000000042af88d065e77c8cc2239327c5edb3a432268e58310001f42f2a2543b76a4166549f7aab2e75bef0aefc5b0f0001f482af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; 74 | | 75 | | bytes memory result = original; 76 | | 77 | | assembly { 78 | | let originalPtr := add(result, 0x20) 79 | | let replacementPtr := add(rev, 0x20) 80 | | 81 | | for { 82 | | let i := 0 83 | | } lt(i, mload(rev)) { 84 | | i := add(i, 0x20) 85 | | } { 86 | | mstore( 87 | | add(originalPtr, add(304, i)), 88 | | mload(add(replacementPtr, i)) 89 | | ) 90 | | } 91 | | } 92 | | require(original.length == result.length, "fail"); 93 | | return result; 94 | | } 95 | | } 96 | |
/workspaces/ethereum/gamma-strategies/gamma-gmx-fuzzing/test/mock/MockGMXUtils.sol 1 | | // SPDX-License-Identifier: GPL-3.0-only 2 | | pragma solidity ^0.8.4; 3 | | 4 | | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | | import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 6 | | import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; 7 | | import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; 8 | | import "@openzeppelin/contracts/utils/math/SafeCast.sol"; 9 | | 10 | | import "../../contracts/libraries/Position.sol"; 11 | | import "../../contracts/libraries/Order.sol"; 12 | | import "../../contracts/libraries/gmx/MarketUtils.sol"; 13 | | import "../../contracts/interfaces/gmx/IDataStore.sol"; 14 | | import "../../contracts/interfaces/gmx/IReader.sol"; 15 | | import "../../contracts/interfaces/gmx/IOrderHandler.sol"; 16 | | import "../../contracts/interfaces/gmx/IOrderCallbackReceiver.sol"; 17 | | import "../../contracts/interfaces/IPerpetualVault.sol"; 18 | | import "../../contracts/interfaces/gmx/IExchangeRouter.sol"; 19 | | import "../../contracts/interfaces/IGmxUtils.sol"; 20 | | import {Test, console} from "forge-std/Test.sol"; 21 | | 22 | | /** 23 | | * @title GMXUtils 24 | | * @dev Contract for Interaction with GMX. 25 | | * this contract is not a library and is not recommended for several perpetual vaults to share a GMXUtils contract 26 | | * We should create one GMXUtils instance for one perpertual vault because all GMX positions are 27 | | * registered as GMXUtils address in GMX protocol 28 | | */ 29 | | 30 | * | contract MockGmxUtils is 31 | | IOrderCallbackReceiver, 32 | | Initializable, 33 | | Ownable2StepUpgradeable 34 | | { 35 | | using SafeERC20 for IERC20; 36 | | 37 | | using SafeCast for uint256; 38 | | 39 | | using Position for Position.Props; 40 | | 41 | | struct PositionData { 42 | | uint256 sizeInUsd; 43 | | uint256 sizeInTokens; 44 | | uint256 collateralAmount; 45 | | uint256 netValue; 46 | | bool isLong; 47 | | } 48 | | 49 | | struct OrderQueue { 50 | | bytes32 requestKey; 51 | | address tokenIn; 52 | | uint256 amountIn; 53 | | bool isSettle; 54 | | } 55 | | 56 | | bytes32 public constant COLLATERAL_TOKEN = 57 | | keccak256(abi.encode("COLLATERAL_TOKEN")); 58 | | 59 | * | bytes32 public constant SIZE_IN_USD = keccak256(abi.encode("SIZE_IN_USD")); 60 | | 61 | | bytes32 public constant SIZE_IN_TOKENS = 62 | | keccak256(abi.encode("SIZE_IN_TOKENS")); 63 | | 64 | | bytes32 public constant COLLATERAL_AMOUNT = 65 | | keccak256(abi.encode("COLLATERAL_AMOUNT")); 66 | | 67 | | bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = 68 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1")); 69 | | 70 | | bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = 71 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE")); 72 | | 73 | | bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = 74 | * | keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR")); 75 | | 76 | | bytes32 public constant INCREASE_ORDER_GAS_LIMIT = 77 | * | keccak256(abi.encode("INCREASE_ORDER_GAS_LIMIT")); 78 | | 79 | | bytes32 public constant DECREASE_ORDER_GAS_LIMIT = 80 | * | keccak256(abi.encode("DECREASE_ORDER_GAS_LIMIT")); 81 | | 82 | | bytes32 public constant SWAP_ORDER_GAS_LIMIT = 83 | * | keccak256(abi.encode("SWAP_ORDER_GAS_LIMIT")); 84 | | 85 | | bytes32 public constant SINGLE_SWAP_GAS_LIMIT = 86 | * | keccak256(abi.encode("SINGLE_SWAP_GAS_LIMIT")); 87 | | 88 | | bytes32 public constant POSITION_FEE_FACTOR = 89 | * | keccak256(abi.encode("POSITION_FEE_FACTOR")); 90 | | 91 | | bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = 92 | * | keccak256(abi.encode("EXECUTE_ORDER_FEATURE_DISABLED")); 93 | | 94 | | bytes32 public constant IS_LONG = keccak256(abi.encode("IS_LONG")); 95 | | 96 | * | bytes32 public constant referralCode = bytes32(0); 97 | | 98 | * | uint256 public constant PRECISION = 1e30; 99 | | 100 | | uint256 public constant BASIS_POINTS_DIVISOR = 10_000; 101 | | 102 | | address public orderHandler; 103 | | IExchangeRouter public gExchangeRouter; 104 | | address router; 105 | | IDataStore public dataStore; 106 | | address public orderVault; 107 | | IReader public reader; 108 | | address public referralStorage; 109 | | 110 | | address public perpVault; 111 | | uint256 public slippage; // GMX swap slippage 112 | | uint256 public priceOffset; // GMX position execution price offset to allow some price impact 113 | | 114 | * | OrderQueue public queue; 115 | | 116 | | event ClaimFundingFees(address token, uint256 amount); 117 | | event ClaimFundingFeeExecutionError(address[], address[], address); 118 | | 119 | | modifier validCallback(bytes32 key, Order.Props memory order) { 120 | * | require(msg.sender == address(orderHandler), "invalid caller"); 121 | | 122 | * | require(order.addresses.account == address(this), "not mine"); 123 | | 124 | * | if (order.numbers.orderType != Order.OrderType.Liquidation) { 125 | * | require(queue.requestKey == key, "invalid request key"); 126 | | } 127 | | 128 | | _; 129 | | } 130 | | 131 | | function initialize( 132 | | address _orderHandler, 133 | | address _gExchangeRouter, 134 | | address _dataStore, 135 | | address _orderVault, 136 | | address _reader, 137 | | address _referralStorage, 138 | | address _router 139 | | ) external initializer { 140 | | __Ownable2Step_init(); 141 | | slippage = 30; 142 | | priceOffset = 30; 143 | | 144 | | orderHandler = _orderHandler; 145 | | gExchangeRouter = IExchangeRouter(_gExchangeRouter); 146 | | dataStore = IDataStore(_dataStore); 147 | | orderVault = _orderVault; 148 | | reader = IReader(_reader); 149 | | referralStorage = _referralStorage; 150 | | router = _router; 151 | | } 152 | | 153 | | receive() external payable {} 154 | | 155 | | /** 156 | | * @notice Retrieves the position information for a given key and market prices. 157 | | * @param key The key representing the position. 158 | | * @param prices The current market prices for the relevant tokens. 159 | | * @return PositionData The data structure containing detailed information about the position. 160 | | */ 161 | * | function getPositionInfo( 162 | | bytes32 key, 163 | | MarketPrices memory prices 164 | * | ) external view returns (PositionData memory) { 165 | * | if (key == bytes32(0)) { 166 | * | return 167 | * | PositionData({ 168 | * | sizeInUsd: 0, 169 | * | sizeInTokens: 0, 170 | * | collateralAmount: 0, 171 | * | netValue: 0, 172 | * | isLong: true 173 | | }); 174 | | } 175 | * | PositionInfo memory positionInfo = reader.getPositionInfo( 176 | * | address(dataStore), 177 | * | referralStorage, 178 | * | key, 179 | * | prices, 180 | * | uint256(0), 181 | * | address(0), 182 | * | true 183 | | ); 184 | * | uint256 netValue; 185 | * | if (positionInfo.basePnlUsd >= 0) { 186 | * | netValue = 187 | * | positionInfo.position.numbers.collateralAmount * 188 | * | prices.shortTokenPrice.min + 189 | * | uint256(positionInfo.basePnlUsd) - 190 | * | positionInfo.fees.borrowing.borrowingFeeUsd - 191 | * | positionInfo.fees.funding.fundingFeeAmount * 192 | * | prices.shortTokenPrice.min - 193 | * | positionInfo.fees.positionFeeAmount * 194 | * | prices.shortTokenPrice.min; 195 | | } else { 196 | * | netValue = 197 | * | positionInfo.position.numbers.collateralAmount * 198 | * | prices.shortTokenPrice.min - 199 | * | (uint256(-positionInfo.basePnlUsd) + 200 | * | positionInfo.fees.borrowing.borrowingFeeUsd) - 201 | * | positionInfo.fees.funding.fundingFeeAmount * 202 | * | prices.shortTokenPrice.min - 203 | * | positionInfo.fees.positionFeeAmount * 204 | * | prices.shortTokenPrice.min; 205 | | } 206 | | 207 | * | return 208 | * | PositionData({ 209 | * | sizeInUsd: positionInfo.position.numbers.sizeInUsd, 210 | * | sizeInTokens: positionInfo.position.numbers.sizeInTokens, 211 | * | collateralAmount: positionInfo 212 | | .position 213 | | .numbers 214 | | .collateralAmount, 215 | * | netValue: netValue, 216 | * | isLong: positionInfo.position.flags.isLong 217 | | }); 218 | | } 219 | | 220 | * | function willPositionCollateralBeSufficient( 221 | | MarketPrices memory prices, 222 | | bytes32 positionKey, 223 | | address market, 224 | | bool isLong, 225 | | uint256 sizeDeltaUsd 226 | * | ) external view returns (bool) { 227 | * | PositionInfo memory positionInfo = reader.getPositionInfo( 228 | * | address(dataStore), 229 | * | referralStorage, 230 | * | positionKey, 231 | * | prices, 232 | * | uint256(0), 233 | * | address(0), 234 | * | true 235 | | ); 236 | * | int256 realizedPnlUsd; 237 | * | if (positionInfo.basePnlUsd > 0) { 238 | | realizedPnlUsd = ((uint256(positionInfo.basePnlUsd) * 239 | | sizeDeltaUsd) / positionInfo.position.numbers.sizeInUsd) 240 | | .toInt256(); 241 | | } else { 242 | * | realizedPnlUsd = -((uint256(-positionInfo.basePnlUsd) * 243 | * | uint256(sizeDeltaUsd)) / 244 | * | uint256(positionInfo.position.numbers.sizeInUsd)).toInt256(); 245 | | } 246 | * | MarketUtils.WillPositionCollateralBeSufficientValues 247 | * | memory values = MarketUtils 248 | | .WillPositionCollateralBeSufficientValues({ 249 | * | positionSizeInUsd: positionInfo.position.numbers.sizeInUsd, 250 | * | positionCollateralAmount: positionInfo 251 | | .position 252 | | .numbers 253 | | .collateralAmount, 254 | * | realizedPnlUsd: realizedPnlUsd, 255 | * | openInterestDelta: -int256(sizeDeltaUsd) 256 | | }); 257 | * | MarketProps memory marketInfo = getMarket(market); 258 | * | (bool willBeSufficient, ) = MarketUtils 259 | | .willPositionCollateralBeSufficient( 260 | * | dataStore, 261 | * | marketInfo, 262 | * | prices, 263 | * | isLong, 264 | * | values 265 | | ); 266 | | 267 | * | return willBeSufficient; 268 | | } 269 | | 270 | * | function getPnl( 271 | | bytes32 key, 272 | | MarketPrices memory prices, 273 | | uint256 sizeDeltaUsd 274 | * | ) external view returns (int256) { 275 | * | if (key == bytes32(0)) { 276 | * | return 0; 277 | | } 278 | * | PositionInfo memory positionInfo = reader.getPositionInfo( 279 | * | address(dataStore), 280 | * | referralStorage, 281 | * | key, 282 | * | prices, 283 | * | sizeDeltaUsd, 284 | * | address(0), 285 | * | true 286 | | ); 287 | | 288 | * | return positionInfo.pnlAfterPriceImpactUsd; 289 | | } 290 | | 291 | | /** 292 | | * @notice Retrieves the position size in USD for a given key. 293 | | * @param key The key representing the position. 294 | | * @return sizeInUsd The size of the position in USD. 295 | | */ 296 | * | function getPositionSizeInUsd( 297 | | bytes32 key 298 | * | ) external view returns (uint256 sizeInUsd) { 299 | * | sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD))); 300 | | } 301 | | 302 | | /** 303 | | * @notice Retrieves the market properties for a given market address. 304 | | * @param market The address of the market to retrieve properties for. 305 | | * @return MarketProps The data structure containing properties of the specified market. 306 | | */ 307 | * | function getMarket( 308 | | address market 309 | * | ) public view returns (MarketProps memory) { 310 | * | return reader.getMarket(address(dataStore), market); 311 | | } 312 | | 313 | | /** 314 | | * @notice Calculates the position fee in USD for a given market and size delta. 315 | | * @param market The address of the market. 316 | | * @param sizeDeltaUsd The USD value of the size delta. 317 | | * @param forPositiveImpact Indicates if the order action balances open interest (true) or not (false). 318 | | * @return positionFeeAmount The calculated position fee amount in USD. 319 | | */ 320 | * | function getPositionFeeUsd( 321 | | address market, 322 | | uint256 sizeDeltaUsd, 323 | | bool forPositiveImpact 324 | * | ) external view returns (uint256 positionFeeAmount) { 325 | * | uint256 positionFeeFactor = dataStore.getUint( 326 | * | keccak256( 327 | * | abi.encode(POSITION_FEE_FACTOR, market, forPositiveImpact) 328 | | ) 329 | | ); 330 | * | positionFeeAmount = (sizeDeltaUsd * positionFeeFactor) / PRECISION; 331 | | } 332 | | 333 | | /** 334 | | * @notice Retrieves the current market prices for a given market. 335 | | * @param market The address of the market to retrieve prices for. 336 | | * @return MarketPrices The data structure containing the current prices for the market's index, long, and short tokens. 337 | | */ 338 | * | function getMarketPrices( 339 | | address market 340 | * | ) external view returns (MarketPrices memory) { 341 | * | MarketPrices memory prices; 342 | * | MarketProps memory marketInfo = reader.getMarket( 343 | * | address(dataStore), 344 | * | market 345 | | ); 346 | * | address oracle = IOrderHandler(orderHandler).oracle(); 347 | * | prices.indexTokenPrice = IOracle(oracle).getPrimaryPrice( 348 | * | marketInfo.indexToken 349 | | ); 350 | * | prices.longTokenPrice = IOracle(oracle).getPrimaryPrice( 351 | * | marketInfo.longToken 352 | | ); 353 | * | prices.shortTokenPrice = IOracle(oracle).getPrimaryPrice( 354 | * | marketInfo.shortToken 355 | | ); 356 | * | return prices; 357 | | } 358 | | 359 | | /** 360 | | * @notice Calculates the execution gas limit for a given order type and callback gas limit. 361 | | * @param orderType The type of order (e.g., MarketIncrease, MarketDecrease, etc.). 362 | | * @param _callbackGasLimit The gas limit specified for the callback. 363 | | * @return executionGasLimit The calculated execution gas limit. 364 | | */ 365 | * | function getExecutionGasLimit( 366 | | Order.OrderType orderType, 367 | | uint256 _callbackGasLimit 368 | * | ) public view returns (uint256 executionGasLimit) { 369 | * | uint256 baseGasLimit = dataStore.getUint( 370 | | ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 371 | | ); 372 | * | uint256 oraclePriceCount = 5; // maximum number of oralce prices 373 | * | baseGasLimit += 374 | * | dataStore.getUint(ESTIMATED_GAS_FEE_PER_ORACLE_PRICE) * 375 | * | oraclePriceCount; 376 | * | uint256 multiplierFactor = dataStore.getUint( 377 | | ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR 378 | | ); 379 | * | uint256 gasPerSwap = dataStore.getUint(SINGLE_SWAP_GAS_LIMIT); 380 | * | uint256 estimatedGasLimit; 381 | * | if (orderType == Order.OrderType.MarketIncrease) { 382 | * | estimatedGasLimit = 383 | * | dataStore.getUint(INCREASE_ORDER_GAS_LIMIT) + 384 | * | gasPerSwap; 385 | * | } else if (orderType == Order.OrderType.MarketDecrease) { 386 | * | estimatedGasLimit = 387 | * | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) + 388 | * | gasPerSwap; 389 | * | } else if (orderType == Order.OrderType.LimitDecrease) { 390 | | estimatedGasLimit = 391 | | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) + 392 | | gasPerSwap; 393 | * | } else if (orderType == Order.OrderType.StopLossDecrease) { 394 | | estimatedGasLimit = 395 | | dataStore.getUint(DECREASE_ORDER_GAS_LIMIT) + 396 | | gasPerSwap; 397 | * | } else if (orderType == Order.OrderType.MarketSwap) { 398 | * | estimatedGasLimit = 399 | * | dataStore.getUint(SWAP_ORDER_GAS_LIMIT) + 400 | * | gasPerSwap; 401 | | } 402 | | // multiply 1.2 (add some buffer) to ensure that the creation transaction does not revert. 403 | * | executionGasLimit = 404 | * | baseGasLimit + 405 | * | ((estimatedGasLimit + _callbackGasLimit) * multiplierFactor) / 406 | | PRECISION; 407 | | } 408 | | 409 | | /** 410 | | * @notice Callback function called by the GMX order execution controller. 411 | | * @dev This function is invoked after the GMX keeper executes the requested order within the next few blocks. 412 | | * @param requestKey The key of the executed order. 413 | | * @param order The data of the executed order. 414 | | * @param eventData The event data associated with the order execution. 415 | | */ 416 | * | function afterOrderExecution( 417 | | bytes32 requestKey, 418 | | Order.Props memory order, 419 | | EventLogData memory eventData 420 | * | ) external override validCallback(requestKey, order) { 421 | * | uint256 claimed; 422 | | 423 | | // Claim funding fees for non-swap orders 424 | * | if (order.numbers.orderType != Order.OrderType.MarketSwap) { 425 | * | address[] memory markets = new address[](2); 426 | * | address[] memory tokens = new address[](2); 427 | * | markets[0] = order.addresses.market; 428 | * | markets[1] = order.addresses.market; 429 | * | MarketProps memory marketInfo = reader.getMarket( 430 | * | address(dataStore), 431 | * | order.addresses.market 432 | | ); 433 | * | tokens[0] = marketInfo.indexToken; 434 | * | tokens[1] = marketInfo.shortToken; 435 | * | try 436 | * | gExchangeRouter.claimFundingFees(markets, tokens, perpVault) 437 | * | returns (uint256[] memory claimedAmounts) { 438 | * | claimed = claimedAmounts[0]; 439 | * | emit ClaimFundingFees(tokens[0], claimed); 440 | | } catch { 441 | * | emit ClaimFundingFeeExecutionError(markets, tokens, perpVault); 442 | | } 443 | | } 444 | * | bytes32 positionKey = keccak256( 445 | * | abi.encode( 446 | * | address(this), 447 | * | order.addresses.market, 448 | * | order.addresses.initialCollateralToken, 449 | * | order.flags.isLong 450 | | ) 451 | | ); 452 | | 453 | | // Determine output token and amount for swap or decrease orders 454 | * | address outputToken; 455 | * | uint256 outputAmount; 456 | * | if ( 457 | * | order.numbers.orderType == Order.OrderType.MarketSwap || 458 | * | order.numbers.orderType == Order.OrderType.MarketDecrease 459 | | ) { 460 | * | outputToken = eventData.addressItems.items[0].value; 461 | * | outputAmount = eventData.uintItems.items[0].value; 462 | | } 463 | | // Construct order result data and notify perpetual vault 464 | * | IGmxUtils.OrderResultData memory orderResultData = IGmxUtils 465 | | .OrderResultData( 466 | * | order.numbers.orderType, 467 | * | order.flags.isLong, 468 | * | order.numbers.sizeDeltaUsd, 469 | * | outputToken, 470 | * | outputAmount, 471 | * | queue.isSettle 472 | | ); 473 | * | IPerpetualVault(perpVault).afterOrderExecution( 474 | * | requestKey, 475 | * | positionKey, 476 | * | orderResultData 477 | | ); 478 | * | delete queue; 479 | | } 480 | | 481 | | /** 482 | | * @notice Callback function called by the GMX order execution controller. 483 | | * @dev This function is called when the submitted order data is incorrect or when a user cancels their order. 484 | | * @param key The request key of the canceled order. 485 | | * @param order The data of the canceled order. 486 | | */ 487 | * | function afterOrderCancellation( 488 | | bytes32 key, 489 | | Order.Props memory order, 490 | | EventLogData memory /* eventData */ 491 | * | ) external override validCallback(key, order) { 492 | * | IGmxUtils.OrderResultData memory orderResultData = IGmxUtils 493 | | .OrderResultData( 494 | * | order.numbers.orderType, 495 | * | order.flags.isLong, 496 | * | order.numbers.sizeDeltaUsd, 497 | * | address(0), 498 | * | 0, 499 | * | queue.isSettle 500 | | ); 501 | * | IPerpetualVault(perpVault).afterOrderCancellation( 502 | * | key, 503 | * | order.numbers.orderType, 504 | * | orderResultData 505 | | ); 506 | * | delete queue; 507 | | } 508 | | 509 | | /** 510 | | * limit order can be set with greater size than the available amount in the pool 511 | | * so when it reaches to the trigger price, it cannot be executed and be frozen. 512 | | * and at that time, `afterOrderFrozen` is called as a callback function. 513 | | * According to the above rule, `afterOrderFrozen` is never called in our contract logic 514 | | */ 515 | | function afterOrderFrozen( 516 | | bytes32 key, 517 | | Order.Props memory order, 518 | | EventLogData memory 519 | | ) external override validCallback(key, order) {} 520 | | 521 | | /** 522 | | * Callback function from GMX to refund remaining gas. 523 | | * @param key request key 524 | | */ 525 | | function refundExecutionFee( 526 | | bytes32 key, 527 | | EventLogData memory 528 | | ) external payable {} 529 | | 530 | | /** 531 | | * @notice 532 | | * Returns the remaining execution fee after flow is completed. 533 | | * @param receipient address to receive the remaining fee 534 | | * @param amount amount of the remaining fee 535 | | */ 536 | | function refundExecutionFee(address receipient, uint256 amount) external { 537 | | require(msg.sender == perpVault, "invalid caller"); 538 | | payable(receipient).transfer(amount); 539 | | } 540 | | 541 | | /** 542 | | * @notice Sets the address of the perpetual vault. 543 | | * @dev This function can only be called once. It requires the perpetual vault address to be non-zero and not already set. 544 | | * @param _perpVault The address of the perpetual vault. 545 | | */ 546 | | function setPerpVault(address _perpVault) external { 547 | | require(_perpVault != address(0), "zero address"); 548 | | require(perpVault == address(0), "already set"); 549 | | perpVault = _perpVault; 550 | | } 551 | | 552 | | // /** 553 | | // * @notice Creates an order with additional callback data. 554 | | // * @dev This function stores the provided callback data and then calls the core `createOrder` function. 555 | | // * @param orderType The type of the order (e.g., MarketIncrease, MarketDecrease, etc.). 556 | | // * @param orderData The data associated with the order. 557 | | // * @param prices The market prices used for order creation. 558 | | // * @param callbackdata Additional callback data to be used during order execution. 559 | | // * @return The request key of the created order. 560 | | // */ 561 | | // function createOrder( 562 | | // Order.OrderType orderType, 563 | | // IGmxUtils.OrderData memory orderData, 564 | | // MarketPrices memory prices, 565 | | // bytes memory callbackdata 566 | | // ) external returns (bytes32) { 567 | | // queue.callbackdata = callbackdata; 568 | | // return createOrder(orderType, orderData, prices); 569 | | // } 570 | | 571 | | /** 572 | | * @notice Creates an order. 573 | | * @dev This function requires the receipient to be the perpetual vault and ensures sufficient ETH balance for the execution fee. 574 | | * It handles token approvals, transfers, and constructs the order parameters before creating the order via `gExchangeRouter`. 575 | | * @param orderType The type of the order (e.g., MarketIncrease, MarketDecrease, etc.). 576 | | * @param orderData The data associated with the order. 577 | | * @return The request key of the created order. 578 | | */ 579 | * | function createOrder( 580 | | Order.OrderType orderType, 581 | | IGmxUtils.OrderData memory orderData 582 | * | ) public returns (bytes32) { 583 | * | require(msg.sender == perpVault, "invalid caller"); 584 | * | uint256 positionExecutionFee = getExecutionGasLimit( 585 | * | orderType, 586 | * | orderData.callbackGasLimit 587 | * | ) * tx.gasprice; 588 | * | require( 589 | * | address(this).balance >= positionExecutionFee, 590 | | "insufficient eth balance" 591 | | ); 592 | | 593 | | // check if execution feature is enabled 594 | * | bytes32 executeOrderFeatureKey = keccak256( 595 | * | abi.encode(EXECUTE_ORDER_FEATURE_DISABLED, orderHandler, orderType) 596 | | ); 597 | * | require( 598 | * | dataStore.getBool(executeOrderFeatureKey) == false, 599 | | "gmx execution disabled" 600 | | ); 601 | | 602 | * | gExchangeRouter.sendWnt{value: positionExecutionFee}( 603 | * | orderVault, 604 | * | positionExecutionFee 605 | | ); 606 | * | if ( 607 | * | orderType == Order.OrderType.MarketSwap || 608 | * | orderType == Order.OrderType.MarketIncrease 609 | | ) { 610 | * | IERC20(orderData.initialCollateralToken).safeApprove( 611 | * | address(router), 612 | * | orderData.amountIn 613 | | ); 614 | * | gExchangeRouter.sendTokens( 615 | * | orderData.initialCollateralToken, 616 | * | orderVault, 617 | * | orderData.amountIn 618 | | ); 619 | * | queue.tokenIn = orderData.initialCollateralToken; 620 | * | queue.amountIn = orderData.amountIn; 621 | | } 622 | * | CreateOrderParamsAddresses 623 | * | memory paramsAddresses = CreateOrderParamsAddresses({ 624 | * | receiver: perpVault, 625 | * | cancellationReceiver: address(perpVault), 626 | * | callbackContract: address(this), 627 | * | uiFeeReceiver: address(0), 628 | * | market: orderData.market, 629 | * | initialCollateralToken: orderData.initialCollateralToken, 630 | * | swapPath: orderData.swapPath 631 | | }); 632 | | 633 | * | CreateOrderParamsNumbers 634 | * | memory paramsNumber = CreateOrderParamsNumbers({ 635 | * | sizeDeltaUsd: orderData.sizeDeltaUsd, 636 | * | initialCollateralDeltaAmount: orderData 637 | | .initialCollateralDeltaAmount, 638 | * | triggerPrice: 0, 639 | * | acceptablePrice: orderData.acceptablePrice, 640 | * | executionFee: positionExecutionFee, 641 | * | callbackGasLimit: orderData.callbackGasLimit, 642 | * | minOutputAmount: orderData.minOutputAmount // this param is used when swapping. is not used in opening position even though swap involved. 643 | | }); 644 | * | CreateOrderParams memory params = CreateOrderParams({ 645 | * | addresses: paramsAddresses, 646 | * | numbers: paramsNumber, 647 | * | orderType: orderType, 648 | * | decreasePositionSwapType: Order 649 | | .DecreasePositionSwapType 650 | | .SwapPnlTokenToCollateralToken, 651 | * | isLong: orderData.isLong, 652 | * | shouldUnwrapNativeToken: false, 653 | * | autoCancel: false, 654 | | referralCode: referralCode 655 | | }); 656 | | 657 | * | (bool success, bytes32 requestKey) = gExchangeRouter.createOrderFUZZ( 658 | * | params 659 | | ); 660 | | 661 | * | require(success, "Order creation failed on GMX exchange router"); 662 | * | queue.requestKey = requestKey; 663 | * | return requestKey; 664 | | } 665 | | 666 | | /** 667 | | * @notice Settles an order by creating a MarketDecrease order with minimal collateral delta amount. 668 | | * @dev This function calculates the execution fee, ensures sufficient ETH balance, sets up the order parameters, 669 | | * and creates the order via the `gExchangeRouter`. 670 | | * @param orderData The data associated with the order, encapsulated in an `OrderData` struct. 671 | | * @return The request key of the created order. 672 | | */ 673 | * | function settle( 674 | | IGmxUtils.OrderData memory orderData 675 | * | ) external returns (bytes32) { 676 | * | require(msg.sender == perpVault, "invalid caller"); 677 | * | uint256 positionExecutionFee = getExecutionGasLimit( 678 | * | Order.OrderType.MarketDecrease, 679 | * | orderData.callbackGasLimit 680 | * | ) * tx.gasprice; 681 | * | require( 682 | * | address(this).balance >= positionExecutionFee, 683 | | "insufficient eth balance" 684 | | ); 685 | * | gExchangeRouter.sendWnt{value: positionExecutionFee}( 686 | * | orderVault, 687 | * | positionExecutionFee 688 | | ); 689 | * | CreateOrderParamsAddresses 690 | * | memory paramsAddresses = CreateOrderParamsAddresses({ 691 | * | receiver: perpVault, 692 | * | cancellationReceiver: address(perpVault), 693 | * | callbackContract: address(this), 694 | * | uiFeeReceiver: address(0), 695 | * | market: orderData.market, 696 | * | initialCollateralToken: orderData.initialCollateralToken, 697 | * | swapPath: new address[](0) 698 | | }); 699 | * | CreateOrderParamsNumbers 700 | * | memory paramsNumber = CreateOrderParamsNumbers({ 701 | * | sizeDeltaUsd: 0, 702 | * | initialCollateralDeltaAmount: 1, 703 | * | triggerPrice: 0, 704 | * | acceptablePrice: 0, 705 | * | executionFee: positionExecutionFee, 706 | * | callbackGasLimit: orderData.callbackGasLimit, 707 | * | minOutputAmount: 0 // this param is used when swapping. is not used in opening position even though swap involved. 708 | | }); 709 | * | CreateOrderParams memory params = CreateOrderParams({ 710 | * | addresses: paramsAddresses, 711 | * | numbers: paramsNumber, 712 | * | orderType: Order.OrderType.MarketDecrease, 713 | * | decreasePositionSwapType: Order 714 | | .DecreasePositionSwapType 715 | | .SwapPnlTokenToCollateralToken, 716 | * | isLong: orderData.isLong, 717 | * | shouldUnwrapNativeToken: false, 718 | * | autoCancel: false, 719 | | referralCode: referralCode 720 | | }); 721 | * | bytes32 requestKey = gExchangeRouter.createOrder(params); 722 | * | queue.requestKey = requestKey; 723 | * | queue.isSettle = true; 724 | * | return requestKey; 725 | | } 726 | | 727 | | /** 728 | | * @notice 729 | | * GMX keepers would not always execute orders in a reasonable amount of time. 730 | | * This function is called when the requested Order is not executed in GMX side. 731 | | */ 732 | | function cancelOrder() external { 733 | | require(msg.sender == perpVault, "invalid caller"); 734 | | require(queue.requestKey != bytes32(0), "zero value"); 735 | | gExchangeRouter.cancelOrder(queue.requestKey); 736 | | } 737 | | 738 | | function claimCollateralRebates( 739 | | address[] memory markets, 740 | | address[] memory tokens, 741 | | uint256[] memory timeKeys, 742 | | address receiver 743 | | ) external { 744 | | require(msg.sender == perpVault, "invalid caller"); 745 | | gExchangeRouter.claimCollateral(markets, tokens, timeKeys, receiver); 746 | | } 747 | | 748 | | function setSlippage(uint256 _slippage) external onlyOwner { 749 | | slippage = _slippage; 750 | | } 751 | | 752 | | function setPriceOffset(uint256 _priceOffset) external onlyOwner { 753 | | priceOffset = _priceOffset; 754 | | } 755 | | 756 | | /** 757 | | * @notice Withdraws all ETH from the contract to the owner's address. 758 | | * @dev This function can only be called by the owner of the contract. 759 | | * @return The balance of ETH withdrawn from the contract. 760 | | */ 761 | | function withdrawEth() external onlyOwner returns (uint256) { 762 | | uint256 balance = address(this).balance; 763 | | payable(msg.sender).transfer(balance); 764 | | return balance; 765 | | } 766 | | } 767 | |